पता लगाएं कि जावा क्लास कहाँ से भरी हुई है


184

क्या किसी को पता है कि प्रोग्रामेटिकली कैसे पता चलता है कि जावा क्लास लोडर वास्तव में क्लास को कहां से लोड करता है?

मैं अक्सर बड़ी परियोजनाओं पर काम करता हूं जहां क्लासपाथ बहुत लंबा हो जाता है और मैन्युअल खोज वास्तव में एक विकल्प नहीं है। मुझे हाल ही में एक समस्या थी जहां क्लास लोडर एक वर्ग का गलत संस्करण लोड कर रहा था क्योंकि यह दो अलग-अलग जगहों पर क्लासपाथ पर था।

तो मुझे क्लासलोडर कैसे मिल सकता है मुझे बताएं कि डिस्क पर वास्तविक क्लास फाइल कहां से आ रही है?

संपादित करें: अगर क्लास लोडर वास्तव में एक संस्करण बेमेल (या कुछ और) के कारण कक्षा को लोड करने में विफल रहता है, तो क्या वैसे भी हम यह पता लगा सकते हैं कि इसे पढ़ने से पहले क्या फ़ाइल पढ़ने की कोशिश कर रही है?


4
@JarrodRoberson मुझे नहीं लगता कि इसे stackoverflow.com/questions/11747833/… का डुप्लिकेट माना जाना चाहिए क्योंकि यह प्रश्न 2008 में पूछा गया था और 2012 में यह प्रश्न पूछा गया था
luke

जवाबों:


189

यहाँ एक उदाहरण है:

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}

यह प्रिंट आउट:

file:/C:/Users/Jon/Test/foo/Test.class

32
निरर्थक टाइपिंग में कटौती करने के लिए, कोई भी छोटे संस्करण का उपयोग कर सकता है: Test.class.getResource("Test.class")जो पैकेज नाम को नहीं दोहराता है।
मेरिटॉन

1
क्या होगा यदि वर्ग संकलित है, जैसे .groovy फ़ाइल से?
ओन्ड्रा žयूका

35
@meriton: या, रिफैक्टोरिन्स से बचे रहने के लिए:Test.class.getResource(Test.class.getSimpleName() + ".class")
leonbloy

1
के लिए BouncyCastleProviderपूर्ण पैकेज का नाम हालांकि आवश्यक है।
पावेल वेलासोव

3
getClassLoader()लौटना संभव है null। इस विधि के विस्तार के लिए यहां देखें
OldCurmudgeon

100

यह पता लगाने का एक और तरीका है कि एक वर्ग को किस स्रोत से लोड किया गया है (स्रोत में हेरफेर किए बिना) विकल्प के साथ जावा वीएम शुरू करना है: -verbose:class


6
यह बहुत अच्छी तरह से काम किया, और साथ अशक्त classloader वर्गों से निपटने की समस्या नहीं है
lexicalscope

2
@ries यदि किसी को इस प्रोग्राम को करने की आवश्यकता नहीं है, तो यह निश्चित रूप से जाने का रास्ता है, और इसने मेरी समस्या को हल किया। हालांकि, ओपी ने विशेष रूप से पूछा था कि यह कैसे प्रोग्रामेटिक रूप से किया जाए।
शांतिबेल

80
getClass().getProtectionDomain().getCodeSource().getLocation();

4
हाँ, हालांकि यह एक सुरक्षा प्रबंधक स्थापित और आवश्यक अनुमति के बिना काम नहीं करता है।
टॉम हॉकिन -

1
FYI करें, NPE = नल सूचक अपवाद। HTH!
एवगेनी सर्गेव

यह विधि तब तक पसंद की जाती है जब तक आपके पास एक उदाहरण का संदर्भ हो, क्योंकि आप एक ही कक्षा को दो अलग-अलग स्थानों से लोड कर सकते हैं।
मिगेल पिंग

1
जावा 9+ मॉड्यूल से कॉल करने पर भी काम नहीं करता है (जो निश्चित रूप से आप 2008 में नहीं जान सकते थे)।
जेफ जी

28

यह वह है जो हम उपयोग करते हैं:

public static String getClassResource(Class<?> klass) {
  return klass.getClassLoader().getResource(
     klass.getName().replace('.', '/') + ".class").toString();
}

यह ClassLoader कार्यान्वयन के आधार पर काम करेगा: getClass().getProtectionDomain().getCodeSource().getLocation()


17

जॉन का संस्करण तब विफल हो जाता है जब ऑब्जेक्ट ClassLoaderपंजीकृत हो जाता है nullजो कि ऐसा लगता है कि यह बूट द्वारा लोड किया गया था ClassLoader

यह विधि उस मुद्दे से संबंधित है:

public static String whereFrom(Object o) {
  if ( o == null ) {
    return null;
  }
  Class<?> c = o.getClass();
  ClassLoader loader = c.getClassLoader();
  if ( loader == null ) {
    // Try the bootstrap classloader - obtained from the ultimate parent of the System Class Loader.
    loader = ClassLoader.getSystemClassLoader();
    while ( loader != null && loader.getParent() != null ) {
      loader = loader.getParent();
    }
  }
  if (loader != null) {
    String name = c.getCanonicalName();
    URL resource = loader.getResource(name.replace(".", "/") + ".class");
    if ( resource != null ) {
      return resource.toString();
    }
  }
  return "Unknown";
}

5

सिर्फ 1 पंक्ति संपादित करें: Main.class

Class<?> c = Main.class;
String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", "");

System.out.println(path);

आउटपुट:

/C:/Users/Test/bin/

शायद बुरा स्टाइल लेकिन ठीक काम करता है!


3

आमतौर पर, हम हार्डकोडिंग का उपयोग नहीं करते हैं। हम पहले ClassName प्राप्त कर सकते हैं, और फिर क्लास URL प्राप्त करने के लिए ClassLoader का उपयोग कर सकते हैं।

        String className = MyClass.class.getName().replace(".", "/")+".class";
        URL classUrl  = MyClass.class.getClassLoader().getResource(className);
        String fullPath = classUrl==null ? null : classUrl.getPath();

होने की आवश्यकता है: URL classUrl = MyClass.class.getClassLoader ()। GetResource ("/" + className);
एंड्रयू कोट

MyClass.class महत्वपूर्ण हिस्सा है - getClass () प्रॉक्सी लौटा सकता है! तब आप MyClass $$ EnhancerBySpringCGLIB $$ a98db882.class और null URL जैसे नाम प्राप्त कर सकते हैं।
जलमासी


1

सरल तरीका:

Println (java.lang.String.class.getResource (String.class.getSimpleName () + "वर्ग।"));

बाहर का उदाहरण:

जार: फ़ाइल: / डी: /Java/jdk1.8/jre/lib/rt.jar /java/lang/String.class

या

स्ट्रिंग obj = "सरल परीक्षण"; Println (obj.getClass () getResource (obj.getClass () getSimpleName () +)।। "वर्ग।");

बाहर का उदाहरण:

जार: फ़ाइल: / डी: /Java/jdk1.8/jre/lib/rt.jar /java/lang/String.class


0

यह दृष्टिकोण दोनों फाइलों और जार के लिए काम करता है:

Class clazz = Class.forName(nameOfClassYouWant);

URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish

-1

यह मानते हुए कि आप नामक एक वर्ग के साथ काम कर रहे हैं MyClass, निम्नलिखित को काम करना चाहिए:

MyClass.class.getClassLoader();

आपको .class फ़ाइल का ऑन-डिस्क स्थान मिल सकता है या नहीं, यह केवल क्लास लोडर पर निर्भर है। उदाहरण के लिए, यदि आप BCEL जैसी किसी चीज़ का उपयोग कर रहे हैं, तो एक निश्चित वर्ग में ऑन-डिस्क प्रतिनिधित्व भी नहीं हो सकता है।


यह क्लास लोड करने के लिए इस्तेमाल किया जाने वाला क्लासऑलडर लौटाता है, है न? यह नहीं पता कि .class फ़ाइल कहाँ है?
कोरे तुगय

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