Java、Classpath、Classloading => 同一个 jar/项目的多个版本

标签 java jar classpath classloader

我知道这对于有经验的编码人员来说可能是一个愚蠢的问题。但是我有一个库(一个 http 客户端),我的项目中使用的一些其他框架/jar 需要它。但它们都需要不同的主要版本,例如:

httpclient-v1.jar => Required by cralwer.jar
httpclient-v2.jar => Required by restapi.jar
httpclient-v3.jar => required by foobar.jar

类加载器是否足够智能以某种方式将它们分开?很可能不是?类加载器如何处理这个问题,以防三个 jar 中的类都相同。加载了哪一个,为什么?

Classloader 是只拾取一个 jar 还是任意混合类?例如,如果一个类是从 Version-1.jar 加载的,那么从同一个类加载器加载的所有其他类都将进入同一个 jar 吗?

你如何处理这个问题?

是否有一些技巧可以以某种方式将 jar 包“合并”到“required.jar”中,以便 Classloader 将它们视为“一个单元/包”,或者以某种方式链接?

最佳答案

类加载器相关的问题是一个相当复杂的问题。 在任何情况下,您都应该记住一些事实:

  • 应用程序中的类加载器通常不止一个。引导类加载器委托(delegate)给适当的。当您实例化一个新类时,会调用更具体的类加载器。如果它没有找到对您尝试加载的类的引用,它会委托(delegate)给它的父类,依此类推,直到您到达引导类加载器。如果它们都没有找到对您尝试加载的类的引用,则会收到 ClassNotFoundException。

  • 如果您有两个具有相同二进制名称的类,可通过同一个类加载器搜索,并且您想知道正在加载其中的哪一个,则只能检查特定类加载器尝试解析类的方式名字。

  • 根据java语言规范,类二进制名称没有唯一性约束,但据我所知,每个类加载器应该是唯一的。

我可以找到一种方法来加载具有相同二进制名称的两个类,它涉及让两个不同的类加载器加载它们(及其所有依赖项),覆盖默认行为。 一个粗略的例子:

    ClassLoader loaderA = new MyClassLoader(libPathOne);
    ClassLoader loaderB = new MyClassLoader(libPathTwo);
    Object1 obj1 = loaderA.loadClass("first.class.binary.name", true)
    Object2 obj2 = loaderB.loadClass("second.class.binary.name", true);

我总是发现类加载器自定义是一项棘手的任务。我宁愿建议避免多次 尽可能不兼容的依赖项。

关于Java、Classpath、Classloading => 同一个 jar/项目的多个版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6105124/

相关文章:

java - 在activiti源代码中更新postgres数据库属性

java - 尝试创建三个类并绘制蜡笔盒。如何在构造函数中绘制蜡笔?

java - Gradle 如何将大量 jar 文件的平面目录转换为 .m2/repository 结构?

Java : create jar executable with dependant jars embedded

java - 在 mac os 中,使用 rxtx 时,加载 gnu.io.RXTXCommDriver 时抛出 java.lang.UnsatisfiedLinkError : no rxtxSerial in java. library.path 错误

java - 如何添加多个 jar )到类路径?

Java Swing - 我如何绘制扩展 JComponent 的类

java - 在eclipse中打开现有的java项目

eclipse - 将 jars 添加到 Eclipse 插件

java - Eclipse 类版本错误