在不同的JAR中加载两个类

时间:2011-04-28 11:22:55

标签: java classpath classloader websphere-6.1

我在不同的JAR中使用相同的包获得了两个类。在之前的版本之前,两个类都是相同的,所以我在加载它们时没有任何问题。现在,其中一个添加了一个新方法,如果我想访问它,不仅应该使用该包导入类,还需要确保具有正确类的jar首先出现在类路径中。

即。 javac -classpath "%classpath%;a.jar;b.jar" MyClasses..

其中a.jar包含我的新方法。

现在,当我的应用程序投入生产时,如何将其部署为EAR文件,以及WEB-INF / lib下的所有库,我该如何确保这一点?

我如何知道哪个罐子优先于另一个?是a.jar的字母顺序是否优先于b.jar?

我已经阅读了这个safe-class-imports-from-jar-files线程,并了解了编写自定义类加载器,但是有更好的简单解决方案吗?我只是要在当前项目中的整个JAR中访问此方法,编写类加载器似乎有点矫枉过正。

请不要问我“为什么在不同的JAR中同一个包有同样的地狱?”它绝对不受我的控制,这需要一些时间才能得到纠正。

环境详细信息:1.5 Java上的IBM WAS 6.1。

如果我没有多大意义,请问我更多问题。提前谢谢!

6 个答案:

答案 0 :(得分:3)

据我所知,从WEB-INF / lib加载的jar的顺序是任意的 - 我问了一个关于JBOSS的类似问题并得到了回复(来自RedHat),它取决于{{1}的顺序返回它们(这不是保证订单)。

自定义类加载器是一个选项,但您是否考虑过重新打包jar - 删除重复的类?

答案 1 :(得分:3)

您可以尝试更改服务器的启动脚本,并使用java -Xbootclasspath在bootclasspath中指定具有正确类的jar。否则无法保证2个罐中的哪一个会加载第一

答案 2 :(得分:2)

Websphere允许您指定在搜索类时查询特定应用程序的类加载器的顺序(类加载器是分层结构的,从最顶层加载JRE类,再加载到WAR中的类加载器类)。

在部署应用程序期间,您可以指定在搜索类时是否查询类加载器的顺序。有两种模式 - Parent first(即首先查询最顶层的类加载器)和parent last(首先查询app classloader)。这可以在EAR和WAR级别指定。

将复制的jar包装到应用程序中的不同位置(例如,一个到EAR的类路径,另一个到WAR的WEB-INF / lib)并适当地设置类加载器orderING可以解决您的问题。但是,如果两个JAR必须位于同一级别(例如WEB-INF / lib),那么在加载重复的类时无法指定将使用哪个JAR。

答案 3 :(得分:1)

一个应用程序中JAR的顺序可能是按字母顺序排列的,但应用程序的顺序可能不是。另外,它取决于服务器如何处理类加载,即它是替换现有类还是跳过新类。

虽然你已经说过,我仍然想提出这样的建议:在一个应用程序中部署多个JAR中的相同类(例如,可能在版本化的jar中发生)总是一个坏主意。你最好花时间来修复它而不是试图搞乱类加载。

答案 4 :(得分:1)

这可能会非常模糊但我确实记得通过弄乱该给定应用程序的WAS管理控制台并使用他们的网络重新安排相关的JAR文件来解决这个问题很长时间UI。不确定这是否是您案件中可接受的步骤,但值得一试,以防一切其他失败。

答案 5 :(得分:1)

假设您可以控制部署,请自行修复类加载。通过将它们以反向加载顺序解压缩到同一目录中然后重新压缩到新的jar中来自己组合有问题的罐子。然后使用新的组合jar部署应用程序。没有重复的类,问题解决了。

或者,只需在部署之前从jar中删除欺骗类。