27

我刚刚解决了另一个 *I-though-I-was-using-this-version-of-a-library-but-appparently-my-app-server-has-already-loaded-an-older-version-of -this-library-*issue(叹气)。

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

提前致谢!

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

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

4

5 回答 5

19

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

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

于 2008-09-26T21:05:08.677 回答
6

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

java.lang.Package .getImplementationVersion() 和 getSpecificationVersion() 和 isCompatibleWith() 听起来他们会做你正在寻找的东西。

您可以通过 this.getClass().getPackage() 等方式获取包。

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

于 2008-10-02T21:01:11.053 回答
3

在当前版本的 Java 中,库版本控制是一个相当模糊的术语,它依赖于使用有用的清单正确打包 JAR。即便如此,正在运行的应用程序要以一种有用的方式将这些信息收集在一起也需要做很多工作。JVM 运行时对您没有任何帮助。

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

有趣的是,Java 7 很可能会包含一个适当的模块版本控制框架来处理这类事情。并不是说这对你有帮助,

于 2008-09-26T14:16:57.300 回答
2

我不认为有一个很好的方法来检查。我不确定你是否想这样做。你需要做的是熟悉你的应用服务器的类加载架构,并理解它是如何工作的。

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

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

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

于 2008-09-26T13:56:30.187 回答
0

肯定有比我做的更好的方法,但我倾向于以非常手动的方式来做。

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

正如我所说,它是手动的,但它可以工作。

于 2008-09-26T13:57:36.923 回答