2012-07-23 25 views
38

'-classpath' komut satırı argümanı verildiğinde java.class.path ayarlanmadığı, ancak bunun yerine bir sınıf yükleyicisi oluşturduğu, üçüncü taraf kodu kullanıyorum, komut satırında belirtilen URL'ler için tüm URL'leri ekler. sınıf yükleyici ve sonra bağlam sınıf yükleyicisi olarak ayarlar. Yazdığım bu kodun bir eklenti sınıfında, bu sınıf yükleyicinin bir örneğini alıyorum ve bir şekilde temel sınıf yolunu geri almak için onu kullanmam gerekiyor, böylece JavaCompiler.getTask'ın bir çağrısında kullanabilirim (.. .) ve diğer bazı kodları anında derleyin. Ancak ClassPath ClassLoader'dan almak için zaten yok gibi görünüyor ve java.class.path unset olduğu gibi, uygulamanın başlangıçta başlatıldığı temel sınıf yoluna erişemiyorum ... Herhangi bir fikir ?Sınıf yükleyiciden sınıf yolu nasıl alınır?

cevap

50

Sınıf yükleyicisi URL'leri kullanıyorsa, bu bir URLClassloader olmalıdır. Erişiminiz olan, ClassLoader numaralı ebeveyniyle birlikte sınıf yolunu tanımlayan URL'lerdir.

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

çalıştı kendi başına sayesinde :) –

+0

da kullanılabilir! –

7

:

basitçe aşağıdakileri yapın URL'leri almak için

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

durumda diğer cevaplara don: durumda ProcessBuilder sınıf yolunda geçmesi gerekiyor, İleride

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

diğer cevaplar çoğu durumda doğrudur, ancak: 't iş, bu deneyin Bazı ayarlardan daha karmaşık hale gelir: ör. Maven, Tomcat ve JUnit kendi sınıf yol desteğine sahiptir ve sistem sınıf yolunu kullanmazlar.

Şimdiye kadar bu (bu kod benim Fast Classpath Scanner projesinden ise) ile gelip başarmış en eksiksiz bir sistemdir:

/** 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

Projeyi takip ederseniz kesinlikle en eksiksiz cevap ve aktif olarak evrim geçirin. –

+0

Arama yığınındaki diğer sınıf yükleyicileri arayan bu kirli yöntem tam da ihtiyacım olan şeydi! Çok teşekkürler! – FelipeKunzler

+0

@ luke-hutchison kütüphaneniz bir hayat kurtarıcıdır! Çeşitli çalışma zamanı ortamları için sınıf yolu alan bir çözüm isteyen herkes için buradaki en iyisi budur. – Dan

0

Damla ClassLoader hiyerarşi ve ilişkili görüntülemek için boş jsp sayfasına bu kodu Her seviyede yüklenmiş kavanozlar.

ziyareti() aşağıda yöntemi Bir şey değil,

<%! 
    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> 
İlgili konular