如何找到类加载器加载的罐子和顺序?

时间:2010-02-01 20:34:39

标签: java jar classloader

我在其他地方找不到这个问题的明确答案,所以我会在这里试试:

是否有某种方式(编程或其他方式)以加载的精确顺序获取Application Classloader加载的JAR /类列表? 应用程序类加载器我的意思是在应用程序服务器(WLS,WAS,JBoss ......)中加载EAR应用程序的类加载器,但显然,它适用于任何类加载器。

因此,为了概括,我想知道的是由指定的类加载器加载的JAR的列表和顺序。不是单个类,通过调用classloader.getPackages()很容易找到,但是这个类加载器加载的JAR文件列表。

4 个答案:

答案 0 :(得分:72)

您是否尝试过使用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]

答案 1 :(得分:13)

简短的回答是否定的。类加载器不需要公开其搜索逻辑。

但是,如果您的类加载器实例恰好是URLClassLoader或子类,那么您可以通过getURLs()方法访问jar /目录列表。根据此类的文档,将按顺序搜索这些URL。

在实践中,如果你试图找出一个类的加载位置, Steve 的答案可能更有用。

答案 2 :(得分:1)

浏览班级的保护域(位置/证书组合)。例如对于PDFParser.class,你可以这样得到它......

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

如果它是从jre类或者背书目录中加载的,那么它会抛出异常,因为这些类加载时没有保护...

答案 3 :(得分:0)

作为替代方法,您可以使用此代码段。结果是一个文件,它由相关的jar文件组成一个类加载器和类文件,这些文件由一个对象的类加载器(类加载器链,包括它的父类直到root类加载器)加载。班级装载者由明星分开。

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);
}