2010-02-01 4 views
37

다른 곳에서이 질문에 대한 명확한 답변을 찾을 수 없으므로 여기에서 시도해 보겠습니다.클래스 로더에 의해로드되는 jar와 순서를 찾는 방법은 무엇입니까?

애플리케이션 클래스 로더에 의해로드 된 JAR/클래스의 목록을 얻는 방법이 있습니까? 로드 된 순서? 애플리케이션 별 클래스 로더 : 애플리케이션 서버 (WLS, WAS, JBoss ...)에서 EAR 애플리케이션을로드하는 클래스 로더를 의미하지만 분명히 모든 클래스 로더에 적용됩니다.

그래서 일반적으로 알기를 원하는 것은 지정된 클래스 로더가로드 한 JAR 목록과 순서입니다. 개별 클래스가 아니기 때문에 classloader.getPackages()를 호출하여 쉽게 찾을 수 있지만이 클래스 로더에 의해로드 된 JAR 파일의 목록

답변

11

짧은 대답은 no입니다. Classloader는 검색 논리를 노출 할 필요가 없습니다.

그러나 클래스 로더 인스턴스가 URLClassLoader 또는 하위 클래스 일 경우 getURLs() 메소드를 통해 jar/디렉토리 목록에 액세스 할 수 있습니다. 이 클래스의 문서별로 해당 URL이 순서대로 검색됩니다.

실제적으로 클래스가로드되는 곳을 찾으려면 스티브의 대답이 더 유용 할 것입니다.

+2

고마워, kdgregory. 이것은 마침내 사용 된 접근법입니다. 기본적으로 런타임에 클래스 로더 계층 구조를 파악하고 사용 가능한 경우 getURLs() 메서드를 사용하여로드 한 리소스 목록을 각 클래스 로더에 쿼리하는 유틸리티를 작성했습니다. WLS와 WAS 모두 잘 작동했습니다. WLS의 경우 자신의 클래스 로더는 URLClassloader를 확장하지 않지만 getClassPath()와는 다른 메소드를 갖습니다. getClassPath()는 클래스 경로 항목의 정렬 된 목록을 반환합니다. 모든 WAS 클래스 로더는 URLClassloader를 확장하는 것처럼 보이므로 getURLs()가 정상적으로 작동합니다. 아직 JBoss에서 시도하지 않았습니다. 마리나 – Marina

58

JVM 옵션 -verbose:class을 사용해 보았습니까? 로드 된 JAR 파일과 클래스를 모두 표시합니다.

예 :

[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

스티브 - 네, 그 옵션을 시도했는데 어떤 클래스 로더와 .jar가 특정 클래스를로드했는지 알기 만하면됩니다. 우리의 어플리케이션은 수천 개의 클래스를 가지고 있기 때문에 결과물이 너무 압도적입니다. :) 나는 kdgregory가 제안한 것과 비슷한 접근 방식을 사용했습니다 - 아래를보십시오. – Marina

0

클래스의 보호 도메인 (위치/인증서 조합)을 탐색하십시오. 예 : PDFParser.class 당신은

그것이 JRE 클래스에서로드 또는 승인 DIRS에서 보호하지 않고 이러한 클래스로드 COS 예외가 발생합니다 경우
PDFParser.class.getProtectionDomain().getCodeSource().getLocation().toString() 

...

0

으로 ... 이런 식으로 그것을 얻을 다른 방법으로이 코드 스 니펫을 사용할 수 있습니다. 결과는 클래스 로더에 관련된 jar 파일과 객체의 클래스 로더 (루트 클래스 로더까지 부모를 포함한 클래스 로더의 체인)에 의해로드되는 클래스 파일로 구성된 파일입니다. 클래스 로더는 별들로 구분됩니다.

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); 
} 
관련 문제