【问题标题】:Classloader issues - How to determine which library versions (jar-files) are loaded类加载器问题 - 如何确定加载了哪些库版本(jar 文件)
【发布时间】:2010-09-13 11:07:11
【问题描述】:

我刚刚解决了另一个 *I-though-I-was-using-this-version-of-a-library-but-apparently-my-app-server-has-already-loaded-an-older-这个库的版本-*问题(叹气)。

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

提前致谢!

[附注在我看来,这是开始使用OSGi module architecture 的一个很好的理由!]

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

【问题讨论】:

    标签: java jar classloader


    【解决方案1】:

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

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

    【讨论】:

    • 听起来我可以用汤姆!明天我会深入研究它。在此先感谢....约翰
    【解决方案2】:

    如果您在 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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

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

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

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

        【讨论】:

        • 至少对于 JBoss 来说,没有那么简单。在某些情况下,JBoss 会从您的 WAR 文件外部加载一个类(例如从服务器/默认/lib),即使该类存在于您的 WAR 文件内部。这取决于各种因素,例如是否启用范围加载(默认值因 JBoss 版本而异)以及是否启用对父类存储库的委托。
        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-14
          • 2010-10-31
          • 1970-01-01
          • 2011-01-11
          • 1970-01-01
          • 1970-01-01
          • 2012-04-04
          相关资源
          最近更新 更多