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

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

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

提前致谢!

[PS在我的视图中开始使用OSGi模块架构的一个很好的理由!]

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

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

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

如果您在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上进行了搜索

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

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

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

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

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

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

最好是将应用程序全局库放在耳朵级别。

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

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

正如我所说,它是手动的,但它的工作原理。