在不同的 JAR 中加载两个类
我在不同的 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 中具有相同的包?”这完全超出我的控制范围,并且需要一些时间才能纠正这个问题。
环境详细信息:IBM WAS 6.1 在其 1.5 Java 上。
如果我没有太多意义,请问我更多问题。提前致谢!
I got two classes with the same package in different JARs. Until the previous version, both classes were identical, so i had no issues in loading them. Now, one of them has a new method added and if I want to access it, not only should I import the class with that package, i also need to make sure the jar with the correct class comes first in the classpath.
i.e. javac -classpath "%classpath%;a.jar;b.jar" MyClasses..
where a.jar
has the class with my new method.
Now, how do i ensure this when my app goes to production, where it's deployed as an EAR file, with all the libraries under WEB-INF/lib?
How do I know which jar gets the preference over the other? Is it the alphabetical order like a.jar is given the first preference over b.jar?
I've read this safe-class-imports-from-jar-files thread and got to know about writing a custom classloader, but is there a better simpler solution that? Cos I'm just going to access this method in that whole JAR in this current project and writing a classloader seems a bit overkill.
And please don't ask me "Why the hell same class with same package in different JARs?" It's absolutely out of my control and it'll take some time to get this corrected.
Environment details: IBM WAS 6.1 on their 1.5 Java.
Please ask me more questions, if I don't make much sense. Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以尝试更改服务器的启动脚本,并使用
java -Xbootclasspath
在 bootclasspath 中指定具有正确类的 jar ...。否则无法保证 2 个 jar 中的哪一个会首先加载。You can try to change the startup script of your server and specify the jar with the correct class in the bootclasspath by using
java -Xbootclasspath
.... Otherwise there is no guarantee which one of the 2 jars will load up first.据我所知,从 WEB-INF/lib 加载 jar 的顺序是任意的 - 我问了一个关于 JBOSS 的类似问题,并得到了答复(来自 RedHat),它取决于
java.io.jar 的顺序。 File.listFiles()
返回它们(并且这不是保证的顺序)。自定义类加载器是一种选择,但是您是否考虑过重新打包 jar - 删除重复的类?
As far as I know, the order of jars being loaded from WEB-INF/lib is arbitrary - I asked a similar question about JBOSS and got the reply ( from RedHat ) that it depends on the order that
java.io.File.listFiles()
returns them in ( and that is not a guaranteed order ).A custom classloader would be an option, but have you considered repackaging the jars - removing the duplicated classes?
Websphere 允许您指定在搜索类时查询特定应用程序的类加载器的顺序(类加载器是分层结构的,从加载 JRE 类的最顶层,一直到加载 WAR 中的类的类加载器)。
在部署应用程序期间,您可以指定搜索类时是否查询类加载器的顺序。有两种模式 - 父级优先(即首先查询最顶层的类加载器)和父级最后(首先查询应用程序类加载器)。这可以在 EAR 和 WAR 级别上指定。
将重复的 jar 打包到应用程序中的不同位置(例如,一个到 EAR 的类路径,另一个到 WAR 的 WEB-INF/lib)并适当地设置类加载器 orderING 可能会解决您的问题。但是,如果您的两个 JAR 必须位于同一级别(例如 WEB-INF/lib),则无法指定在加载重复的类时使用哪一个。
Websphere allows you to specify the order in which classloaders of a particular application are inquired when searching for a class (the classloaders are hierarchically structured, from the topmost that loads JRE classes, down to classloader loading classes in your WAR).
During deployment of an app, you can specify if the order of inquiring the classloaders when searching for a class. There are two modes - Parent first (i.e. query the topmost classloader first) and parent last (query the app classloader first). This can be specified on both EAR and WAR level.
Packaging the duplicated jars to different locations in the app (e.g. one to EAR's classpath, the other to WAR's WEB-INF/lib) and setting the classloader orderING apropriately may solve your problem. However, if both your JARs have to be on the same level (e.g. WEB-INF/lib), then there's no way to specify which one will be used when loading the duplicated class.
一个应用程序中 JAR 的顺序可能是按字母顺序排列的,但应用程序的顺序可能不是。此外,它还取决于服务器如何处理类加载,即是否替换现有类或跳过新类。
尽管您已经说过,但我仍然想给出这样的建议:在一个应用程序中部署的多个 JAR 中使用相同的类(例如,版本化的 jar 可能会发生这种情况)始终是一个坏主意。你最好花时间来解决这个问题,而不是试图搞乱类加载。
The order of the JARs in one application is likely to be alphabetical but the order of applications might not. Additionally, it depends on how the server handles classloading, i.e. whether it replaces existing classes or skips the new ones.
Although you already stated that, I'd still like to give that advice: Having the same class in multiple JARs deployed in one application (which could happen with versioned jars, for example) is always a bad idea. Your better off to invest the time to fix that instead of trying to mess with class loading.
这可能会显得相当模糊,但我确实记得很久很久以前就解决了这个问题,方法是摆弄给定应用程序的 WAS 管理控制台,并使用其 Web UI 重新排列相关的 JAR 文件。不确定这对于您的情况是否是可接受的步骤,但值得一试,以防万一其他一切都失败。
This might come out to be pretty vague but I do remember resolving this issue a long time back by messing around with the WAS admin console for that given application and rearranging the relevant JAR files using their web UI. Not sure if this is an acceptable step in your case but worth a try in case everything else fails.
假设您对部署有一定的控制权,请自行修复类加载。通过以反向加载顺序将有问题的 jar 解压缩到同一目录中,然后重新压缩到新的 jar 中,您可以自己合并有问题的 jar。然后使用新的组合 jar 部署应用程序。没有重复的类,问题解决了。
或者,在部署之前从 jar 中删除重复类。
assuming you have some control over the deployment, fix the classloading yourself. combine the problematic jars yourself by unzipping them in reverse loading order into the same directory and then re-zipping into a new jar. then deploy the app with the new combo jar. no duplicate classes, problem solved.
or, just delete the dupe classes from the jars before deploying.