类加载器问题 - 如何确定加载哪些库版本(jar文件)

时间:2008-09-26 13:34:03

标签: java jar classloader

我刚刚解决了另一个*我 - 虽然我正在使用这个版本的库 - 但显然是我的应用程序服务器已经已经加载了一个更老的 - 版本的这个库 - *问题(叹气)。

是否有人知道验证(或监控)您的应用程序是否可以访问所有相应的jar文件或加载的类版本的好方法?

提前致谢!

[P.S。在我的视图中开始使用OSGi module architecture的一个很好的理由!]

更新This文章也有帮助!通过将JBoss的类加载器写入日志文件,它让我深入了解JBoss的类加载器。

5 个答案:

答案 0 :(得分:18)

如果您正在使用JBoss,则有一个MBean(类加载器存储库iirc),您可以在其中请求已加载某个类的所有类加载器。

如果所有其他方法都失败了,那么总会有'java -verbose:class',它将为每个正在加载的类文件打印jar的位置。

答案 1 :(得分:5)

如果您在jar清单中有适当的版本信息,则有检索和测试版本的方法。无需手动阅读清单。

java.lang.Package。getImplementationVersion()和getSpecificationVersion()以及isCompatibleWith()听起来像是在做你正在寻找的东西。

您可以使用this.getClass()。getPackage()以及其他方式获取Package。

java.lang.Package的javadoc没有为这些属性提供特定的清单属性名称。快速谷歌搜索将其调整为http://java.sun.com/docs/books/tutorial/deployment/jar/packageman.html

答案 2 :(得分:3)

在当前版本的Java中,库版本控制是一个相当糟糕的术语,它依赖于JAR与正确的清单一起正确打包。即便如此,正在运行的应用程序仍然需要以有用的方式收集这些信息。 JVm运行时没有任何帮助。

我认为最好的办法是在构建时强制执行此操作,使用Ivy或Maven等依赖管理工具来获取所有内容的正确版本。

有趣的是,Java 7可能会包含一个适当的模块版本控制框架,正是为了这类事情。这并不能帮助你,

答案 3 :(得分:2)

我认为没有一个好方法可以检查。而且我不确定你是否愿意这样做。您需要做的是熟悉app-server的类加载架构,并了解其工作原理。

它的工作原理的简化说明是:EJB或web-app将首先在其自己的模块(ejb-jar或war)中声明的库中查找类或资源。如果在那里找不到类,则类加载器将请求转发给其父类加载器,该父类加载器是声明的依赖项(通常是ejb)或应用程序类加载器,它负责加载在ear包中声明的库和资源。 。如果仍未找到类或资源,则将请求转发到将在其自己的类路径中查找的应用服务器。

这就是说,您应该记住,Java EE模块(web-app,ejb)将始终从最近范围内的jar加载类。例如,如果你在war文件中打包log4j v1,在ear level级别将log4j v2打包,并将log4j v3放在app-server的类路径中,模块将在其自己的模块中使用jar。拿走它,它将使用耳朵水平。把它取出来,它将使用app-server的类路径中的那个。当模块之间存在复杂的依赖关系时,事情变得更加棘手。

最好是将应用程序全局库放在耳边。

答案 4 :(得分:0)

必须有比我这样做更好的方式,但我倾向于以非常手动的方式做到这一点。

  1. 每个Jar必须在文件名中包含它的版本号(如果它没有更改它的名称)。
  2. 每个应用程序都有自己的类路径。
  3. 必须有理由开始使用更新的Jar(新版本)。不要只是因为它可用而改变,因为它为你提供了所需的功能。
  4. 每个版本必须包含所有需要的JAR。
  5. 我保留一个Version类,它知道它需要的Jars列表(这被编码到源文件中),并且可以在运行时根据类路径中的Jars列表进行检查。
  6. 正如我所说,它是手动的,但它有效。