अनुपलब्ध एनोटेशन रनटाइम पर ClassNotFoundException का कारण क्यों नहीं बनता है?


91

निम्नलिखित कोड पर विचार करें:

A.java:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@interface A{}

C.java:

import java.util.*;

@A public class C {
        public static void main(String[] args){
                System.out.println(Arrays.toString(C.class.getAnnotations()));
        }
}

उम्मीद के मुताबिक काम करना और चलाना:

$ javac *.java
$ java -cp . C
[@A()]

लेकिन फिर इस पर विचार करें:

$ rm A.class
$ java -cp . C
[]

मुझे उम्मीद है कि यह एक को फेंक देगा ClassNotFoundException, क्योंकि @Aगायब है। लेकिन इसके बजाय, यह चुपचाप एनोटेशन को गिरा देता है।

क्या यह व्यवहार कहीं-कहीं जेएलएस में प्रलेखित है, या यह सूर्य के जेवीएम का एक प्रश्न है? इसके लिए तर्क क्या है?

यह चीजों के लिए सुविधाजनक लगता है javax.annotation.Nonnull( जैसे लगता है कि यह @Retention(CLASS)वैसे भी होना चाहिए था ), लेकिन कई अन्य एनोटेशन के लिए ऐसा लगता है कि यह विभिन्न खराब चीजों को रनटाइम पर हो सकता है।

जवाबों:


90

JSR-175 (एनोटेशन) के लिए पहले के सार्वजनिक ड्राफ्ट में, चर्चा की गई थी कि कंपाइलर और रनटाइम को अज्ञात एनोटेशन को अनदेखा करना चाहिए, एनोटेशन के उपयोग और घोषणा के बीच एक शिथिल युग्मन प्रदान करने के लिए। एक विशिष्ट उदाहरण तैनाती विन्यास को नियंत्रित करने के लिए एक ईजेबी पर एप्लिकेशन सर्वर विशिष्ट एनोटेशन का उपयोग था। यदि एक ही सेम को एक अलग एप्लिकेशन सर्वर पर तैनात किया जाना चाहिए, तो यह सुविधाजनक होगा यदि रनटाइम ने केवल NoClassDefFoundError को बढ़ाने के बजाय अज्ञात एनोटेशन को अनदेखा किया।

यदि शब्दांकन थोड़ा अस्पष्ट है, तो भी मुझे लगता है कि जो व्यवहार आप देख रहे हैं वह JLS 13.5.7 में निर्दिष्ट है: "... एनोटेशन को हटाने से जावा प्रोग्रामिंग भाषा में कार्यक्रमों के द्विआधारी निरूपण के सही जुड़ाव पर कोई प्रभाव नहीं पड़ता है। । " मैं इसकी व्याख्या इस तरह करता हूं जैसे कि एनोटेशन को हटा दिया जाता है (रनटाइम पर उपलब्ध नहीं है), प्रोग्राम को अभी भी लिंक और रन करना चाहिए और इसका मतलब है कि प्रतिबिंब के माध्यम से पहुंचने पर अज्ञात एनोटेशन को बस अनदेखा कर दिया जाता है।

सन की जेडीके 5 की पहली रिलीज ने इसे सही ढंग से लागू नहीं किया, लेकिन यह 1.5.0_06 में तय किया गया था। आप बग डेटाबेस में प्रासंगिक बग 6322301 पा सकते हैं , लेकिन यह दावा करने के अलावा किसी भी विशिष्टताओं की ओर इशारा नहीं करता है कि "JSR-175 कल्पना लीड के अनुसार, अज्ञात एनोटेशन को getAnnotations द्वारा अनदेखा किया जाना चाहिए"।


35

JLS का हवाला देते हुए:

9.6.1.2 अवधारण के स्रोत स्रोत कोड में ही मौजूद हो सकते हैं, या वे किसी वर्ग या इंटरफ़ेस के द्विआधारी रूप में मौजूद हो सकते हैं। बाइनरी में मौजूद एक एनोटेशन जावा प्लेटफॉर्म के चिंतनशील पुस्तकालयों के माध्यम से रन-टाइम पर उपलब्ध हो सकता है या नहीं भी हो सकता है।

एनोटेशन प्रकार एनोटेशन। नोटेशन का उपयोग उपरोक्त संभावनाओं के बीच चयन करने के लिए किया जाता है। यदि एक एनोटेशन टाइप T से मेल खाता है, और T में एक (मेटा-) एनोटेशन मीटर है, जो एनोटेशन से मेल खाता है। ध्यान दें, तब:

  • यदि m में एक ऐसा तत्व है जिसका मान एनोटेशन है। रिटेंशन पॉलीसीसरी। एक जावा कंपाइलर को यह सुनिश्चित करना होगा कि वह वर्ग या इंटरफ़ेस के द्विआधारी प्रतिनिधित्व में मौजूद नहीं है जिसमें एक प्रकट होता है।
  • यदि m में एक ऐसा तत्व है जिसका मान एनोटेशन है। RetentionPolicy.CLASS, या annotation.RetentionPolicy.RUNTIME एक जावा कंपाइलर को यह सुनिश्चित करना चाहिए कि वर्ग या इंटरफ़ेस के द्विआधारी प्रतिनिधित्व में प्रतिनिधित्व किया गया है जिसमें एक प्रकट होता है, जब तक कि एम एक स्थानीय चर घोषणा को एनोटेट नहीं करता है। । बाइनरी प्रतिनिधित्व में स्थानीय चर घोषणा पर एक एनोटेशन कभी भी बरकरार नहीं रहता है।

यदि T में मेटा (मेटा-) एनोटेशन मीटर नहीं है जो एनोटेशन से संबंधित है। ध्यान दें, तो एक जावा कंपाइलर को टी का इलाज करना चाहिए जैसे कि उसके पास ऐसा मेटा-एनोटेशन मीटर होता है जिसमें एलीमेंट होता है जिसका मान annot है ।etentionPolicy.CLASS।

तो RetentionPolicy.RUNTIME सुनिश्चित करता है कि एनोटेशन को बाइनरी में संकलित किया गया है लेकिन बाइनरी में मौजूद एनोटेशन को रनटाइम पर उपलब्ध नहीं होना है


9

यदि आपके पास वास्तव में ऐसा कोड है जो @A पढ़ता है और इसके साथ कुछ करता है, तो कोड में कक्षा A पर निर्भरता है, और यह ClassNotFoundException को फेंक देगा।

यदि नहीं, तो कोई कोड @A के बारे में विशिष्ट रूप से परवाह नहीं करता है, तो यह तर्क है कि @A वास्तव में मायने नहीं रखता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.