2012-07-23 12 views
38

मैं कुछ तृतीय पक्ष कोड का उपयोग कर रहा हूं, जब '-classpath' कमांड लाइन तर्क दिया गया है java.class.path सेट नहीं करता है, बल्कि इसके बजाय केवल क्लासलोडर बनाता है, कमांड लाइन निर्दिष्ट क्लासपाथ पर आइटम्स के लिए सभी यूआरएल जोड़ता है क्लासलोडर, और फिर इसे संदर्भ क्लासलोडर के रूप में सेट करता है। मैंने जो कोड लिखा है, उसके लिए प्लगइन क्लास में, मुझे इस क्लासलोडर का एक उदाहरण मिलता है, और अंतर्निहित क्लासपाथ को वापस पाने के लिए इसका उपयोग करने की ज़रूरत है, ताकि मैं इसका उपयोग JavaCompiler.getTask (के आवेषण में कर सकूं। ।) और फ्लाई पर कुछ अन्य कोड संकलित करें। हालांकि कक्षा क्लाउडर से क्लासपाथ प्राप्त करने के लिए वैसे भी प्रतीत नहीं होता है, और जैसा कि java.class.path अनसेट है, मैं अंतर्निहित क्लासपाथ तक पहुंच नहीं पा रहा हूं जिसे एप्लिकेशन प्रारंभ में शुरू किया गया था ... कोई भी विचार ?क्लासलोडर से क्लासपाथ कैसे प्राप्त करें?

उत्तर

50

यदि क्लासलोडर यूआरएल का उपयोग करता है, तो यह URLClassloader होना चाहिए। आपके पास जो यूआरएल है, वह यूआरएल है जो क्लासपाथ को इसके माता-पिता ClassLoader के साथ इसके साथ परिभाषित करता है।

यूआरएल के लिए, बस निम्न कार्य करें: अन्य उत्तर

StringBuffer buffer = new StringBuffer(); 
for (URL url : 
    ((URLClassLoader) (Thread.currentThread() 
     .getContextClassLoader())).getURLs()) { 
    buffer.append(new File(url.getPath())); 
    buffer.append(System.getProperty("path.separator")); 
} 
String classpath = buffer.toString(); 
int toIndex = classpath 
    .lastIndexOf(System.getProperty("path.separator")); 
classpath = classpath.substring(0, toIndex); 
ProcessBuilder builder = new ProcessBuilder("java", 
    "-classpath", classpath, "com.a.b.c.TestProgram"); 
+0

काम किया, धन्यवाद :) –

+0

आपका स्वागत है! –

7

भविष्य में संदर्भ के लिए, काम नहीं करते, इसे आजमाएं:

ClassLoader cl = ClassLoader.getSystemClassLoader(); 
URL[] urls = ((URLClassLoader) cl).getURLs(); 
for (URL url: urls) { 
    System.out.println(url.getFile()); 
} 
5

मामले में डॉन: मामले में आप ProcessBuilder के लिए कक्षा रास्ते में पारित करने के लिए की जरूरत है

((URLClassLoader) (Thread.currentThread().getContextClassLoader())).getURLs() 
12

अन्य उत्तर अधिकांश स्थितियों में सही हैं, लेकिन यह कुछ सेटिंग्स में उससे अधिक जटिल हो जाता है: उदा। Maven, Tomcat और जुनीट का अपना वर्गपाथ समर्थन है और वे सिस्टम क्लासपाथ का उपयोग नहीं करते हैं।

अब तक यह सबसे पूरी प्रणाली के साथ मैं (इस कोड को मेरी Fast Classpath Scanner परियोजना से है) आने में कामयाब रहे है:

/** The unique elements of the classpath, as an ordered list. */ 
private final ArrayList<File> classpathElements = new ArrayList<>(); 

/** The unique elements of the classpath, as a set. */ 
private final HashSet<String> classpathElementsSet = new HashSet<>(); 

/** Clear the classpath. */ 
private void clearClasspath() { 
    classpathElements.clear(); 
    classpathElementsSet.clear(); 
} 

/** Add a classpath element. */ 
private void addClasspathElement(String pathElement) { 
    if (classpathElementsSet.add(pathElement)) { 
     final File file = new File(pathElement); 
     if (file.exists()) { 
      classpathElements.add(file); 
     } 
    } 
} 

/** Parse the system classpath. */ 
private void parseSystemClasspath() { 
    // Look for all unique classloaders. 
    // Keep them in an order that (hopefully) reflects the order in which class resolution occurs. 
    ArrayList<ClassLoader> classLoaders = new ArrayList<>(); 
    HashSet<ClassLoader> classLoadersSet = new HashSet<>(); 
    classLoadersSet.add(ClassLoader.getSystemClassLoader()); 
    classLoaders.add(ClassLoader.getSystemClassLoader()); 
    if (classLoadersSet.add(Thread.currentThread().getContextClassLoader())) { 
     classLoaders.add(Thread.currentThread().getContextClassLoader()); 
    } 
    // Dirty method for looking for any other classloaders on the call stack 
    try { 
     // Generate stacktrace 
     throw new Exception(); 
    } catch (Exception e) { 
     StackTraceElement[] stacktrace = e.getStackTrace(); 
     for (StackTraceElement elt : stacktrace) { 
      try { 
       ClassLoader cl = Class.forName(elt.getClassName()).getClassLoader(); 
       if (classLoadersSet.add(cl)) { 
        classLoaders.add(cl); 
       } 
      } catch (ClassNotFoundException e1) { 
      } 
     } 
    } 

    // Get file paths for URLs of each classloader. 
    clearClasspath(); 
    for (ClassLoader cl : classLoaders) { 
     if (cl != null) { 
      for (URL url : ((URLClassLoader) cl).getURLs()) { 
       if ("file".equals(url.getProtocol())) { 
        addClasspathElement(url.getFile()); 
       } 
      } 
     } 
    } 
} 

/** Override the system classpath with a custom classpath to search. */ 
public FastClasspathScanner overrideClasspath(String classpath) { 
    clearClasspath(); 
    for (String pathElement : classpath.split(File.pathSeparator)) { 
     addClasspathElement(pathElement); 
    } 
    return this; 
} 

/** 
* Get a list of unique elements on the classpath (directories and files) as File objects, preserving order. 
* Classpath elements that do not exist are not included in the list. 
*/ 
public ArrayList<File> getUniqueClasspathElements() { 
    return classpathElements; 
} 
+1

यदि आप परियोजना का पालन करते हैं तो निश्चित रूप से सबसे पूर्ण उत्तर और सक्रिय रूप से विकसित हो रहा है। –

+0

उस गंदे विधि जो कॉल स्टैक पर किसी अन्य क्लासलोडर की तलाश में है, वही था जो मुझे चाहिए था! बहुत बहुत धन्यवाद! – FelipeKunzler

+0

@ ल्यूक-हचिसन आपकी लाइब्रेरी एक जीवन बचतकर्ता है! किसी ऐसे समाधान के लिए जो विभिन्न रनटाइम वातावरण के लिए क्लासपाथ प्राप्त करता है, यह सबसे अच्छा है। – Dan

0

ड्रॉप एक खाली jsp पेज में इस कोड को classloader पदानुक्रम और संबद्ध देखने पर जार प्रत्येक स्तर पर लोड किया गया।

यात्रा() नीचे दी गई विधि भी अपने आप ही इस्तेमाल किया जा सकता है

<%! 
    public void visit(StringBuilder sb, int indent, ClassLoader classLoader) { 
     if (indent > 20 || classLoader == null) 
      return; 
     String indentStr = new String(new char[indent]).replace("\0", " "); 
     sb.append("\n"); 
     sb.append(indentStr); 
     sb.append(classLoader.getClass().getName()); 
     sb.append(":"); 
     if (classLoader instanceof java.net.URLClassLoader) { 
      java.net.URL[] urls = ((java.net.URLClassLoader)classLoader).getURLs(); 
      for (java.net.URL url : urls) { 
       sb.append("\n"); 
       sb.append(indentStr); 
       sb.append(url); 
      } 
     } 
     sb.append("\n"); 
     visit(sb, indent + 1, classLoader.getParent()); 
    } 

%> 

<% 
StringBuilder sb = new StringBuilder(); 
visit(sb,1,this.getClass().getClassLoader()); 
%> 
<pre> 
<%=sb%> 
</pre> 
संबंधित मुद्दे