Java - 获取JVM中加载的所有类的列表

65 java reflection jvm

我想得到一个属于某个包的所有类的列表以及他们所有的孩子.这些类可能已经加载,也可能没有加载到JVM中.

Bri*_*new 103

这不是一个程序化的解决方案,但你可以运行

java -verbose:class ....
Run Code Online (Sandbox Code Playgroud)

并且JVM将转储它正在加载的内容以及从何处加载.

[Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar]
[Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参见此处


zap*_*app 29

使用Reflections库,它很简单:

Reflections reflections = new Reflections("my.pkg", new SubTypesScanner(false));
Run Code Online (Sandbox Code Playgroud)

这将扫描包含my.pkg包的url/s中的所有类.

  • false参数表示 - 不排除默认情况下排除的Object类.
  • 在某些情况下(不同的容器),您可以传递classLoader以及参数.

因此,获取所有类有效地获取Object的所有子类型,传递:

Set<String> allClasses = 
    reflections.getStore().getSubTypesOf(Object.class.getName());
Run Code Online (Sandbox Code Playgroud)

(普通的方法reflections.getSubTypesOf(Object.class)会导致将所有类加载到PermGen中并且可能会抛出OutOfMemoryError.你不想这样做......)

如果要获取Object(或任何其他类型)的所有直接子类型,而不是一次性获取其传递子类型,请使用以下命令:

Collection<String> directSubtypes = 
    reflections.getStore().get(SubTypesScanner.class).get(Object.class.getName());
Run Code Online (Sandbox Code Playgroud)

  • 您只需要忍受将另一个库添加到项目中的痛苦。在Java中使用该语言时,不允许使用“简单”一词。您给我希望,认为这是JDK的一部分,是标准的反映。 (2认同)

eis*_*eis 20

这个问题有多个答案,部分原因是模糊的问题 - 标题是讨论由JVM加载的类,而问题的内容是"JVM可能加载也可能不加载".

假设OP需要由给定类加载器由JVM加载的类,并且只需要那些类 - 我的需要 - 还有一个解决方案(在此详述)如下所示:

import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class CPTest {

    private static Iterator list(ClassLoader CL)
        throws NoSuchFieldException, SecurityException,
        IllegalArgumentException, IllegalAccessException {
        Class CL_class = CL.getClass();
        while (CL_class != java.lang.ClassLoader.class) {
            CL_class = CL_class.getSuperclass();
        }
        java.lang.reflect.Field ClassLoader_classes_field = CL_class
                .getDeclaredField("classes");
        ClassLoader_classes_field.setAccessible(true);
        Vector classes = (Vector) ClassLoader_classes_field.get(CL);
        return classes.iterator();
    }

    public static void main(String args[]) throws Exception {
        ClassLoader myCL = Thread.currentThread().getContextClassLoader();
        while (myCL != null) {
            System.out.println("ClassLoader: " + myCL);
            for (Iterator iter = list(myCL); iter.hasNext();) {
                System.out.println("\t" + iter.next());
            }
            myCL = myCL.getParent();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

关于它的一个巧妙的事情是你可以选择一个你想检查的任意类加载器.然而,如果类加载器类更改的内部结构可能会中断,那么它将被用作一次性诊断工具.


dav*_*veb 7

我还建议您编写-javagent代理,但使用getAllLoadedClasses方法而不是转换任何类.

要与客户端代码(普通Java代码)同步,请创建套接字并通过它与代理进行通信.然后,您可以在需要时触发"列出所有类"方法.


Ami*_*ani 6

上述方法的另一种方法是创建一个外部代理,java.lang.instrument用于找出加载的类并使用-javaagent交换机运行程序:

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

public class SimpleTransformer implements ClassFileTransformer {

    public SimpleTransformer() {
        super();
    }

    public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) throws IllegalClassFormatException {
        System.out.println("Loading class: " + className);
        return bytes;
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法的另一个好处是可以为您提供有关哪个ClassLoader加载给定类的信息.


yoA*_*ex5 5

JVM 中加载的所有类的列表

Oracle 文档中,您可以使用-Xlog可以写入文件的选项。

java -Xlog:class+load=info:classloaded.txt
Run Code Online (Sandbox Code Playgroud)


小智 -9

好吧,我所做的只是列出类路径中的所有文件。它可能不是一个光荣的解决方案,但它工作可靠,并为我提供了我想要的一切,甚至更多。

  • @jtzero:我不知道OP使用了什么,但对我来说 System.getProperty("java.class.path") 效果很好。 (5认同)
  • 你能给一个代码片段吗?这样其他人就可以从您的解决方案中受益。谢谢 (3认同)
  • 在尝试回答更多问题之前,请阅读[如何写出一个好的答案?](http://stackoverflow.com/help/how-to-answer)。 (3认同)