Java 用于隔离jar的类加载器(类标识危机)

Java 用于隔离jar的类加载器(类标识危机),java,jar,classloader,conflict,Java,Jar,Classloader,Conflict,我使用的jarX具有与我自己的依赖项冲突的嵌入式依赖项,因此我创建了一个类加载器来将jarX的依赖项与我的主类加载器隔离开来 jarX在我的应用程序的类路径之外,但我使用jarX类的类在我的类路径中,因此当我实例化通过自定义类加载器加载的类时,我遇到了类身份危机,其形式是ClassCastException,因为JVM版本的类被认为与自定义类加载器加载的类不同 我发现他们通过反射只与自定义类加载器加载的类交互来解决类似的问题,这似乎解决了这个问题 感觉应该比这容易。有谁知道更好的方法来处理这个问

我使用的jarX具有与我自己的依赖项冲突的嵌入式依赖项,因此我创建了一个类加载器来将jarX的依赖项与我的主类加载器隔离开来

jarX在我的应用程序的类路径之外,但我使用jarX类的类在我的类路径中,因此当我实例化通过自定义类加载器加载的类时,我遇到了类身份危机,其形式是ClassCastException,因为JVM版本的类被认为与自定义类加载器加载的类不同

我发现他们通过反射只与自定义类加载器加载的类交互来解决类似的问题,这似乎解决了这个问题


感觉应该比这容易。有谁知道更好的方法来处理这个问题吗?

最简单的方法是打开jarX,删除有问题的类,然后完成。在JAR中嵌入依赖项是一种不好的做法,除非JAR仅用作独立的可运行fat JAR。用作库的JAR不应嵌入依赖项

当您注意到人们在jar中打包第三方类时,我建议您向他们指出,这通常不是一个好主意,并鼓励他们不要这样做。如果一个项目提供了一个包含所有依赖项的可运行fat jar,那就好了。但是,它不应该是他们提供的唯一罐子。还应提供没有任何第三方代码的普通JAR或JAR集。在极少数情况下,第三方代码被修改并且必须包含在内,应该在提供程序的包命名空间下完成,而不是在原始第三方的包命名空间下完成


最后,对于构建模块化Java应用程序和处理类加载器隔离的真正解决方案,请查看几个实现或项目中的一个。

您能用完整的stacktrace发布它是哪个jar以及它重叠的类吗?看看我写的这个,在WAR中生成一个重复类列表,有一个选项可以排除相同大小的重复

可以采取以下措施来解决这一问题:

  • 通过逐一分析重叠的原因,尝试减少重复的数量。为完全重复的JAR添加maven排除
  • 检查同一个jar是否有一个版本没有您可以使用的依赖项,它是哪个jar,xerces,等等
  • 如果没有没有没有依赖项的jar,那么可以排除与jarX重叠的另一个jar,看看应用程序是否仍然工作。这意味着所有需要jar的组件都有一个兼容版本的jarX库
  • 根据所需库的版本,将应用程序分为两个部分。这将减少
这些措施可能更易于长期维护

如果前面的措施无效:

  • 打开jar,删除重复的类,并在maven存储库中发布一个不同名称的jarX补丁
  • 您可以将nexus配置为透明地为打补丁的jar而不是未打补丁的jar提供服务

  • 如果您的容器支持OSGI,那就更好了,但是如果您不使用OSGI容器进行开发,那么应用程序将无法在开发中工作


我目前能想到的最简单的解决方案是使用与jarX所需库相同的版本。然而,由于某些政策的原因,这并不总是可能的。如果您有maven(也可以在gradle中工作?),您可以指定从加载中排除jarX所需的某些库,从而使用您的库。但是,这只有在两个JAR使用相同的公共接口时才可能。问题是它们是嵌入的且不完整(缺少未使用的方法),这确实使删除有问题的类变得可行,但由于我太懒,该解决方案被认为不合适,因此,我现在使用的是一个坏的类加载器:)您可以发布哪些JAR冲突以及完整的堆栈跟踪,您使用的是哪台服务器吗?