java - 在 JVM 运行时查找类

标签 java classloader

有没有办法通过使用类加载器信息来查找扩展特定类的所有类名?

更详细的说明

我有一个 jar 文件,其中包含 3 个类 X(extends A)、Y(extends A )和 Z (扩展 B)。我已将此 jar 文件放入类路径中并启动 JVM(调用某个类的 main 方法)。现在从这个 main 方法有什么方法可以找到 A 的子类吗?即类XY,因为它们扩展了类A

最佳答案

不幸的是,没有简单的方法可以做到这一点。在类加载器加载特定类之前,JVM 没有有关该类的信息。但要让类加载器实际加载类,您必须知道类的名称。先有鸡还是先有蛋的问题。

但是,还有其他一些但更复杂的方法。

  1. 要确定运行应用程序时类路径上有哪些 .jar 文件,您可以调用 System.getProperty("java.class.path") 然后拆分沿 File.separatorChar 字符的类路径条目。类路径条目可能很多,请考虑以某种方式过滤它们(仅限制到特定目录,忽略诸如 rt.jar 等标准条目)
  2. 如果您知道哪个 .jar 文件包含您感兴趣的类,则可以使用类 JarFile 的实例打开它。然后,您可以迭代所有条目(例如 .class 文件),并从 JAR 文件中的内部路径构建它们的完全限定类名。
  3. 有了类名,你就可以调用Class.forName()来加载类,然后你可以使用反射来获取每个类的父类(super class),以判断它是否扩展了你的类。是否属于特定类别。

请注意,此方法非常消耗资源,您使 JVM 实际上从一个 .jar 文件(或多个 .jar 文件)加载所有类,甚至如果您以后不再使用它们。这浪费了相当多的 af 内存(PermGen 空间)。

有一些操作 Java 字节码和类文件的低级库(请参阅 BCELASM )。使用它们,您将能够确定类的父类(super class),而无需实际(类)加载它,因此这种方式更快并且使用更少的内存。

您的问题类似于部署 Web 应用程序时 JavaEE 应用程序服务器的工作方式。为了找出要加载和初始化哪些类(例如 HTTP servlet),他们必须检查 Web 存档中的所有类,以查找特定的 Java 注释或父类(super class)。不过,他们至少知道要扫描哪个 .war 文件。例如,Apache Tomcat 使用 BCEL 而不是 Java 类加载机制。

如果您正在为应用程序设计某种动态类加载机制,请考虑其他设计选项来缩小加载程序必须扫描的类的数量,以找到要加载的正确类:告诉 的确切名称>.jar 文件而不是将其放在类路径上,而是使用 JAR 中的一些元信息(您可以使用前面提到的 JarFile 来读取 META-INF/manifest 中的条目.mf 文件)来指定要查找的类等。

关于java - 在 JVM 运行时查找类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9124740/

相关文章:

使用自定义类加载器时出现 java.lang.ClassCastException

Java:无法关闭 HtmlUnit 日志消息(2016)

java - 如何使用 XJC 使用一些现有的 Java 类生成 JAXB 类?

java - Guice IoC 怎么样?

java - 类加载器 loadClass 抛出 ClassNotFoundException

java - Java Bootstrap 类加载器是如何加载的?

java - getResourceAsStream 在新环境下失败?

reflection - 在运行时使用 JDK 编译器时的内存泄漏

java - 使用临时列表时出现 ConcurrentModificationException

java - 从不同类的不同线程修改 JavaFX gui