Java 9中可靠的配置

5
Java 9项目Jigsaw的主要目标之一是实现可靠配置。也就是说,Java 9承诺解决类路径机制的缺陷,该缺陷允许java启动器在运行程序时不确保所有必需的类都可用于加载,在过去会导致java.lang.NoClassDefFoundError错误。
这是通过在module-info.java中声明模块依赖关系以及全新的--module-path选项来实现的。在启动Java应用程序之前,会分析模块图。
然而,我仍然可以做以下操作。
1. 假设我有两个模块com.spacey.explorer和com.spacey.rocket。com.spacey.explorer使用由com.spacey.rocket模块定义和导出的类com.spacey.rocket.RocketZ。编译和JAR两个模块后一切正常运行。
2. 现在,我从com.spacey.rocket模块中删除了com.spacey.rocket.RocketZ类型,然后只重新编译和重新JAR这个模块。
3. 我使用新编译的com.spacey.rocket模块运行先前编译的com.spacey.explorer模块。
4. 我得到... java.lang.NoClassDefFoundError,这可能发生在应用程序运行时间长达4小时后。
有没有一种方法来确保运行Java应用程序时不仅验证模块图(模块路径)的完整性,而且还进行实际类型可访问性的全面检查?

不,模块系统从不检查类。 - Mordechai
你能详细说明一下第三点的意思吗?如果 c.s.rocket 中有一个缺失的类,你如何运行新编译的 c.s.explorer 呢? - Naman
@nullpointer 就像 (1) 中一样 java --module-path ../jars-dir --module com.spacey.explorer/com.spacey.explorer.MissionApp - malloc4k
2个回答

5

有没有一种方法可以确保在运行Java应用程序时,不仅验证模块图(模块路径)的完整性,还要进行实际类型可访问性的全面检查?

不在JVM内部。模块系统在工件级别上运作,并且如果声称是正确模块的工件存在,则它将很高兴。除此之外,不会执行进一步的检查。

话虽如此,JDeps应该能够帮助您。它分析您的项目及其依赖项,并在单个类的级别上运作。它将指出找不到的依赖项。

在您的示例中:

$ jdeps -R --module-path jars-dir -m com.spacey.explorer

> com.spacey.explorer    -> com.spacey.rocket    not found

实际上,jdeps 可以胜任这项工作。值得注意的是,添加 -verbose:class 选项可以获得更多信息(类级别)的输出。 - malloc4k

4
我认为其他答案在技术方面有所帮助,但除此之外,我认为你对“可靠”的理解有些错误。 这篇文章谈到了“脆弱的”类路径:
所有这些都是脆弱类路径的结果。这意味着类加载器没有好的机制来区分同名的已加载类或隔离由一个类加载器加载的类和由另一个类加载器加载的类。
而模块提供的答案是:
Java模块将提供可靠的配置和强大的封装。如果存在不兼容性,则会在构建时发现,而不是在应用程序在生产中开始运行后的某个不确定时间。
换句话说,我认为你误解了模块的设计目的,认为它们旨在防止所有种类的LinkageError(所有No..FoundError问题的根源)。模块使您更容易构建事物。您找到了一个很好的例子,说明这并不一定能够完美地保证运行时问题的安全性。
换句话说,您对“可靠模块”的解释与Jigsaw项目实际试图提供的“可靠模块”的承诺不相符。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接