【问题标题】:Find classes with same full qualified name in Java during runtime在运行时在 Java 中查找具有相同全名的类
【发布时间】:2021-04-25 21:26:19
【问题描述】:

假设我有一个 jar a.jar 和一个类 com.company.ma.MyClass

package com.company.ma
public class MyClass {
  public void someMethod() {
    System.out.println("Hey");
  }
}

还有另一个 jar b.jar 有一个类 com.company.ma.MyClass 但不同的实现。

package com.company.ma
public class MyClass {
  public void anotherMethod() {
    System.out.println("This is different");
  }
}

这些类具有相同的全限定名,但它们不同。

如何在类路径中找到具有给定完整限定名的所有类,例如 com.company.ma.MyClass 并打印它的位置?在这个例子中,我希望在两个不同的 jars 中有两个名为 com.company.ma.MyClass 的类

【问题讨论】:

  • 您也许可以使用ByteBuddy 之类的工具在运行时替换加载的类,这对您来说可能已经足够了。
  • ClassLoader.getResources("com/company/ma/MyClass.class")

标签: java reflection jar classpath


【解决方案1】:

我认为每个(完全限定的)类名只能引用 JRE 中的一个类;参见例如this question。所以你不能同时通过反射访问它们。

也许您可以编写自己的 ClassLoader 来以您需要的任何方式捕获和处理冲突。

您还可以使用java.util.jar.JarFile 打开任何 .jar 文件并解析其清单,其中包含 .jar 中包含的所有 .class 文件的列表。

【讨论】:

    【解决方案2】:

    您不能为此使用反射,因为您只能与加载的类进行迭代,并且具有指定名称的类加载器只能加载一个类。

    您必须创建单独的类加载器(如URLClassLoader),并让第一个解析第一个jar,第二个应该在第二个jar 中查找。您可以使用 ClassLoader.loadClass() 从 jar 中加载类。更多信息 herehere。最好不要在类路径中包含这两个版本,因为第二个链接表明如果系统类加载器可以自行加载类,它可能无法工作。

    另一种选择是加载一个类,做任何你想做的事情,卸载它并加载你的另一个类。您可以通过以下方式卸载类:

    1. 删除对类及其加载器的所有引用,并触发垃圾回收,如 here 所述。
    2. 使用ByteBuddy 等操作工具来操作JVM 的行为。

    这将无法同时使用这些类,但如果您只想比较或查找它们可能就足够了。

    如果您只想定位类而不使用它们,您可以手动解析 jar 文件并计算相应的 .class 文件,如 here 所述。

    简短摘要:如果类路径中同时包含两个类,则只能加载其中一个。如果你在类路径上都没有,你可以通过一些手动工作来加载它们。如果您只想找到它们,请解析 jar 文件。

    【讨论】:

      猜你喜欢
      • 2018-11-15
      • 2018-12-25
      • 1970-01-01
      • 1970-01-01
      • 2012-06-18
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      相关资源
      最近更新 更多