2010-08-25 14 views
76

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

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) वैसे भी होना चाहिए), लेकिन कई अन्य टिप्पणियों के लिए ऐसा लगता है जैसे यह रनटाइम पर कई बुरी चीजें हो सकती है।

उत्तर

81

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

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

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

32

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

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

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

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

टी एक (मेटा) एनोटेशन मीटर कि annotation.Retention से मेल खाती है नहीं है, तो एक जावा संकलक टी का इलाज करना होगा जैसे कि वह करता है एक साथ इस तरह के एक मेटा-एनोटेशन मीटर है तत्व जिसका मूल्य एनोटेशन है। रीटिशन पॉलिसी। क्लास।

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

-1

एनोटेशन कोड के संचालन पर कोई सीधा प्रभाव नहीं होने के लिए नहीं है वे एनोटेट करते हैं।
हालांकि, @Retention(RetentionPolicy.RUNTIME) का उपयोग करके एनोटेशन रनटाइम पर उपलब्ध हो जाते हैं।

अब, मेरा अनुमान है कि @Retention उपलब्ध नहीं है और इसलिए अनदेखा किया गया है। इसका तात्पर्य है कि अन्य एनोटेशन रनटाइम पर उपलब्ध नहीं कराए जाते हैं।
कोई अपवाद नहीं है क्योंकि डिफ़ॉल्ट रूप से टिप्पणियां अनदेखा की जाती हैं। केवल @Retention की उपस्थिति में वे माना जाता है।

शायद यदि आप शोर @Retention उपलब्ध कराते हैं, तो शिकायत होगी। (इस बारे में निश्चित नहीं)

+5

@ पुनरावृत्ति java.lang.annotation में है - यह कैसे उपलब्ध नहीं हो सकता है? –

7

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

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

संबंधित मुद्दे