2012-06-05 16 views
46

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

// lowercase/src/testcase/a.java 
package testcase; 
public class a { 
    public static String myCase() { 
     return "lower"; 
    } 
} 

// uppercase/src/testcase/A.java 
package testcase; 
public class A { 
    public static String myCase() { 
     return "upper"; 
    } 
} 

तीन ग्रहण कोड युक्त परियोजनाओं ऊपर available from my website हैं।

अगर मैं ऐसा तरह दोनों वर्गों पर myCase बुला की कोशिश:

System.out.println(A.myCase()); 
System.out.println(a.myCase()); 

typechecker सफल होता है, लेकिन जब मैं कक्षा फ़ाइल को चलाने के कोड सीधे ऊपर मैं द्वारा उत्पन्न:

Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)

में जावा, नाम सामान्य मामले में संवेदनशील हैं। कुछ फाइल सिस्टम (जैसे विंडोज) केस असंवेदनशील हैं, इसलिए मुझे आश्चर्य नहीं है कि उपरोक्त व्यवहार होता है, लेकिन ऐसा लगता है कि गलत है। दुर्भाग्यवश जावा विनिर्देश अजीब रूप से गैर-महत्वपूर्ण हैं कि कौन से वर्ग दिखाई दे रहे हैं। Java Language Specification (JLS), Java SE 7 Edition (धारा 6.6.1, पेज 166) कहते हैं:

If a class or interface type is declared public, then it may be accessed by any code, provided that the compilation unit (§7.3) in which it is declared is observable.

धारा 7.3 में, JLS अत्यंत अस्पष्ट संदर्भ में एक संकलन इकाई के observability परिभाषित करता है:

All the compilation units of the predefined package java and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable.

Java Virtual Machine Specification इसी तरह अस्पष्ट है (धारा 5.3.1):

The following steps are used to load and thereby create the nonarray class or interface C denoted by [binary name] N using the bootstrap class loader [...] Otherwise, the Java virtual machine passes the argument N to an invocation of a method on the bootstrap class loader to search for a purported representation of C in a platform-dependent manner.

यह सब महत्व के घटते क्रम में चार सवालों की ओर जाता है:

  1. क्या कोई गारंटी है कि प्रत्येक वर्ग में डिफ़ॉल्ट वर्ग लोडर (ओं) द्वारा कौन से वर्ग लोड किए जा सकते हैं? दूसरे शब्दों में, क्या मैं एक वैध, लेकिन खराब जेवीएम को कार्यान्वित कर सकता हूं, जो java.lang और java.io को छोड़कर किसी भी वर्ग को लोड नहीं करेगा?
  2. यदि कोई गारंटी है, तो ऊपर दिए गए उदाहरण में व्यवहार गारंटी का उल्लंघन करता है (यानी व्यवहार एक बग है)?
  3. क्या हॉटस्पॉट लोड a और A एक साथ बनाने का कोई तरीका है? एक कस्टम वर्ग लोडर काम लिखना होगा?
+3

तो मुझे इस सीधे .. आप मिल गया है दो समान नाम वाले वर्गों 'testcase.a' मिलता है और' testcase.A ', आपके क्लासपाथ पर दो * अलग * निर्देशिकाओं में (क्योंकि आप उन्हें एक ही निर्देशिका में एक असंवेदनशील फाइल सिस्टम पर नहीं रख सकते हैं) - और आप सोच रहे हैं कि JVM को लोड करने के लिए सही वर्ग फ़ाइल क्यों नहीं मिल रही है? –

+0

@GregHewgill आपने परिदृश्य को मेरे प्रश्न की शुरुआत में सही तरीके से वर्णित किया है, लेकिन मेरे प्रश्न अधिक व्यापक हैं। –

+0

ठीक है, "क्लासपाथ" का पूरा विचार जेएलएस और जेवीएमएस के दृष्टिकोण से मंच-निर्भर है। उन दस्तावेज़ों में से कोई भी आपको इस प्रश्न को हल करने में मदद करेगा। –

उत्तर

18
  • Are there any guarantees about which classes are loadable by the bootstrap class loader in every JVM?

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

  • If there are any guarantees, does the behavior in the example above violate the guarantee (i.e. is the behavior a bug)?
  • Is there any way to make "standard" JVMs load a and A simultaneously? Would writing a custom class loader work?

जावा लोड एक फ़ाइल नाम है कि तब classpath पर खोज की है में वर्ग का पूरा नाम मैप करके कक्षाएं। इस प्रकार testcase.atestcase/a.class और testcase.A पर जाता है testcase/A.class पर जाता है। कुछ फाइल सिस्टम इन चीज़ों को मिश्रित करते हैं, और जब किसी से पूछा जाता है तो दूसरे की सेवा कर सकते हैं। दूसरों को यह सही लगता है (विशेष रूप से, जेएआर फाइलों में इस्तेमाल किए गए ज़िप प्रारूप का संस्करण पूरी तरह से केस-संवेदी और पोर्टेबल है)। ऐसा कुछ भी नहीं है जो जावा इसके बारे में कर सकता है (हालांकि एक आईडीई .class फ़ाइलों को मूल एफएस से दूर रखकर आपके लिए इसे संभाल सकता है, मुझे नहीं पता कि वास्तव में कोई वास्तव में क्या करता है और जेडीके का javac निश्चित रूप से स्मार्ट नहीं है) ।

हालांकि यह ध्यान देने योग्य एकमात्र बिंदु नहीं है: कक्षा फाइलें आंतरिक रूप से जानती हैं कि वे किस कक्षा के बारे में बात कर रहे हैं। की अनुपस्थिति फ़ाइल से वर्ग की अपेक्षा है कि लोड विफल हो जाता है, जिससे आपको NoClassDefFoundError प्राप्त हुआ। आपको जो मिला वह एक समस्या थी (कम से कम कुछ समझ में गलत तैनाती) जिसे पता चला और मजबूती से निपटाया गया। सैद्धांतिक रूप से, आप एक क्लासलोडर बना सकते हैं जो खोज को रखकर ऐसी चीजों को संभाल सकता है, लेकिन परेशान क्यों है? कक्षा फ़ाइलों को एक जेएआर के अंदर रखकर चीजों को और अधिक मजबूत तरीके से ठीक किया जाएगा; उनको सही ढंग से संभाला जाता है।

आम तौर पर, अगर आप वास्तविक एक बहुत के लिए इस समस्या में चला रहे हैं, उत्पादन कर रही करने के लिए ले एक यूनिक्स पर बनाता है एक केस-संवेदी फाइल सिस्टम के साथ (जेनकींस की तरह एक सीआई प्रणाली की सिफारिश की है) और लगता है जो डेवलपर्स नामकरण कर रहे हैं केवल मामला अंतर के साथ कक्षाएं और उन्हें रोकें क्योंकि यह बहुत भ्रमित है!

+0

पुन: "उन्हें रोक दें।" ई कैन'टी! मैं जावा बाइटकोड को संकलित करने वाली दूसरी भाषा के लिए एक कंपाइलर लिख रहा हूं। स्रोत में पहचानकर्ताओं को लक्ष्य (बाइटकोड) में पहचानकर्ताओं से मेल खाना चाहिए, और दूसरी भाषा में कई महत्वपूर्ण उदाहरणों में एक ही मामला असंवेदनशील नाम है। –

+0

ठीक है, इस तरह की चीजों से निपटने का सामान्य तरीका अनुवाद में मामले को सामान्य बनाना है। –

+0

मैंने यही किया है, लेकिन यह जावा और दूसरी भाषा के बीच अंतःक्रियाशीलता को और अधिक अजीब बनाता है। जावा कोड जो अन्य भाषा में लिखे गए कोड को संकलित करके बनाए गए वर्गों को संदर्भित करता है, को स्रोत नामों के बजाय सामान्यीकृत नामों का उपयोग करना होता है। उस ने कहा, मेरी परियोजना का विवरण बिंदु के बगल में थोड़ा सा है, मैं कक्षा लोडिंग के जेवीएम स्पेक के विवरण और हॉटस्पॉट जेवीएम के विशेष व्यवहार को समझने में अधिक रुचि रखता हूं। –

-2

फ़ोल्डरों के बारे में न सोचें।

अपनी कक्षाओं के लिए स्पष्ट अलग-अलग नामस्थान ("पैकेज") का उपयोग करें, और शायद अपने वर्गों से मेल खाने के लिए फ़ोल्डर का उपयोग करें। आप अपने कोड, जावा के लिए एक पैकेज का उल्लेख नहीं करते जब

package com.mycompany.mytool; 

// "com.mycompany.mytool.MyClass" 

public class MyClass 
{ 
    // ... 
} // class MyClass 

:

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

पैकेज आपके कोड में "वर्चुअल" फ़ोल्डर्स की तरह हैं, और आपके क्लासपाथ पर या अपने सभी पैकेज पर लागू होते हैं। आपके पास एक ही आईडी के साथ कई कक्षाएं हो सकती हैं, लेकिन, यदि वे अलग-अलग पैकेज में हैं, और आप निर्दिष्ट करते हैं कि कौन सा पैकेज देखना है, तो आपको कोई समस्या नहीं होगी।

बस मेरे 2 सेंट, जावा कॉफी

1

डोनल के ठीक विवरण को जोड़ने के लिए है, लेकिन मुझे संक्षेप में इस वाक्यांश पर विचार करते हैं थोड़ा छोड़ देता है:

... Java classes with the same case-insensitive name ...

नाम और सामान्य रूप में स्ट्रिंग्स खुद को में कभी नहीं केस-संवेदी हैं, यह केवल वहाँ व्याख्या है जो हो सकता है। और दूसरी बात, जावा ऐसी व्याख्या नहीं करता है।

तो, क्या आपने सोचा था की एक सही शब्दों होगा:

... Java classes whose file representations in a case-insensitive file-system have identical names ...

+0

एक नाम केस-असंवेदनशील हो सकता है (और मुझे एक अजीब मेनफ्रेम पर बहुत लंबे समय तक केस असंवेदनशील तारों का सामना करना पड़ा है; brrr!) लेकिन जावा के नाम हमेशा केस-संवेदी होते हैं, और हर किसी के तार केस-संवेदी होते हैं ... ठीक है, निश्चित रूप से कम से कम मेरे पूरे करियर। –

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