2010-02-01 9 views
37

nie mogłem znaleźć jasnej odpowiedzi na to pytanie gdzie indziej, więc spróbuję tutaj:Jak znaleźć, które słoiki i w jakiej kolejności są ładowane przez program ładujący klasy?

Czy jest jakiś sposób (programowy lub inny), aby uzyskać listę słoiki/klas załadowane przez classloader aplikacji w określonym aby zostały załadowane? Przez Application Classloader mam na myśli program ładujący klasy, który ładuje aplikację EAR na serwerze aplikacji (WLS, WAS, JBoss ...), ale oczywiście dotyczy każdego programu ładującego klasy.

Tak więc, aby uogólnić, chciałbym się dowiedzieć, jaka jest lista i kolejność JARów załadowanych przez określony program ładujący klasy. Nie pojedynczych klas, które można łatwo znaleźć, wywołując metodę classloader.getPackages(), ale listę plików JAR załadowanych przez ten program ładujący klasy.

Odpowiedz

11

Krótki odpowiedź nie. Classloaders nie są wymagane, aby ujawnić swoją logikę wyszukiwania.

Jeśli jednak twoja instancja klasy ładującej się jest URLClassLoader lub podklasą, masz dostęp do listy słoików/katalogów za pomocą metody getURLs(). W przypadku dokumentu dla tej klasy te adresy URL będą wyszukiwane w kolejności.

W praktyce, jeśli próbujesz dowiedzieć się, gdzie klasa jest ładowana, odpowiedź Steve'a jest prawdopodobnie bardziej przydatna.

+2

Dzięki, kdgregory. Jest to podejście, które w końcu wykorzystałem - w zasadzie napisałem narzędzie, które rozumie hierarchię programu ładującego klasy w środowisku wykonawczym i wysyła zapytanie do każdego programu ładującego klasy, jaka lista zasobów została załadowana przy użyciu metody getURLs(), jeśli jest dostępna. Udało się to dobrze zarówno dla WLS, jak i WAS. W przypadku WLS, ich własne programy ładujące klasy nie rozszerzają URLClassloader, ale mają inną metodę, getClassPath(), która zwraca uporządkowaną listę pozycji klasy classpath. I wszystkie programy ładujące klasy WAS wydają się rozszerzać URLClassloader, więc getURLs() działało bez zarzutu. Nie próbowałem jeszcze tego na JBoss. Marina – Marina

58

Czy próbowałeś użyć opcji JVM -verbose:class. Wyświetla wszystkie załadowane pliki JAR i klasy.

przykład:

[Opened C:\Program Files\JDK160~1\jre\lib\rt.jar] 
[Loaded java.lang.Object from C:\Program Files\JDK160~1\jre\lib\rt.jar] 
+0

Dzięki, Steve - tak, próbowałem tej opcji i działa dobrze, jeśli jesteś po prostu zainteresowany wiedząc, które classloader i od tego, co JAR ładowane konkretną klasę. Wynik jest jednak zbyt przytłaczający, ponieważ nasza aplikacja ma tysiące klas :). Użyłem podejścia podobnego do tego, co sugerował kdgregory - patrz poniżej. – Marina

0

Przejdź przez domenę ochrony klasy (połączenie lokalizacja/certyfikat). na przykład dla PDFParser.class masz to tak ...

PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString() 

Jeśli jest ładowany z klasy JRE lub z zatwierdzonymi katalogów będzie to wyjątek cos tych klas obciążenia bez ochrony ...

0

Jak w inny sposób możesz użyć tego fragmentu kodu. Wynikiem jest plik, który składa się z powiązanych plików JAR do plików modułu ładującego klasę i klasy, które są ładowane przez obiekty ładujące klasy (łańcuch ładowań klasy, łącznie z jego rodzicami, aż do klasowego programu ładującego klasy root). Klasy-ładowarki są rozdzielone gwiazdami.

Object obj = this; 
ClassLoader classLoader = obj.getClass().getClassLoader(); 
File file = new File("classlodersClassesJars.txt"); 
if(file.exists()) { 
    file.delete(); 
} 
if(classLoader != null) { // to escape from system classes that are loaded by bootstrap class-loader such as String. 
    do { 
     try { 
      Class clClass = classLoader.getClass(); 
      while(clClass != ClassLoader.class){ 
        clClass = clClass.getSuperclass(); 
      } 
      java.lang.reflect.Field domainField = clClass.getDeclaredField("domains"); 
      java.lang.reflect.Field classesField = clClass.getDeclaredField("classes"); 
      domainField.setAccessible(true); 
      classesField.setAccessible(true); 
      HashSet domains = (HashSet<String>) domainField.get(classLoader); 
      Vector classes = (Vector) classesField.get(classLoader); 
      FileOutputStream fos = new FileOutputStream("classlodersClassesJars.txt", true); 
      fos.write(("\n******************** " + classLoader.toString() + "\n").getBytes()); 
      fos.write(Arrays.toString(classes.toArray()).getBytes()); 
      Object[] reverseDomains = domains.toArray(); 
      org.apache.commons.lang.ArrayUtils.reverse(reverseDomains); 
      fos.write(Arrays.toString(reverseDomains).getBytes()); 
      fos.close(); 
      classLoader = classLoader.getParent(); 
     } catch (Exception exception) { 
      exception.printStackTrace(); 
      // TODO 
     } 
    } while (classLoader.getParent() != null); 
} 
Powiązane problemy