6

我了解 Java 平台模块系统 (JPMS) 对大型应用程序的好处,但是是否有任何理由将小型库或应用程序变成(单个)模块?如果是这样,模块化 Jar 文件是实现此目的的最佳方法,还是首选常规方法?

展望未来,模块化 v. 类路径程序是否会对性能产生影响?

4

3 回答 3

8

直接的性能影响包括以下内容:

  • 模块化应用程序可以选择使用jlink以减少可分发运行时的大小:它只使用您需要的模块。因此,如果您不需要 Swing、Corba 等,它不会驻留在磁盘上。(更多信息在这里)。
  • 模块化应用程序使用模块图进行类加载;这个算法比类路径的线性搜索要快得多(更多信息在这里)。

这决不能保证您的应用程序会更快,但不可否认,上述内容具有吸引力。

从长远来看,考虑一下:

  • 虽然在 JDK 9 中是实验性的,但有一个 AOT 编译器(用于 Linux x64)会将java.base模块编译为本机代码。这可能是未来 Java 版本的前进方向。当然,这将改善未来的启动时间。(再次,更多信息在这里
于 2017-08-16T14:59:57.607 回答
3

如果是这样,模块化 Jar 文件是实现此目的的最佳方法,还是首选常规方法?

我不确定您所说的“正常方法”是什么意思 -模块化 JAR是创建模块系统将为其创建模块的工件的“正常方法”。

[我]有什么理由将一个小库或应用程序变成一个(单个)模块?

是的,有几个:

  • 创建模块化应用程序或使用模块化库的开发人员受益于可靠的配置,他们只能在所有依赖项都存在的情况下启动他们的应用程序 - 无论应用程序/库有多大,这都是一个好处。

  • 作为库设计师,您可以隐藏内部结构。虽然强封装只有在将模块化 JAR 放在模块路径上时才有效,但模块描述符仍会在代码中记录您的意图,并允许您更肆无忌惮地更改代码。应用程序开发人员也受益,因为他们不再会意外地依赖不受支持的实现细节。

  • 即使在小型应用程序和库中,服务也可用于解耦功能的不同方面并使代码更易于扩展。

  • 只有“真正的”模块(与自动模块相反)可以包含在运行时映像中jlink。不提供模块化 JAR 会使您的用户失去这种可能性的库。

另请注意,您永远不知道哪个小应用程序或库可能会变成更大的东西。:)

展望未来,模块化 v. 类路径程序是否会对性能产生影响?

虽然构建模块图和验证模块需要时间,但模块系统应该使用改进的类加载策略来弥补:它为每个包记录哪个模块导出它并直接从该模块加载该包中的类型,而不必扫描整个类路径。无论哪种方式,我认为这不应该是决定性因素。

于 2017-08-16T20:55:37.743 回答
0

发现此链接内容丰富
http://www.javaworld.com/article/2878952/java-platform/modularity-in-java-9.html

JAR 文件还不够模块化吗?

JAR 文件和它们运行的​​部署环境大大改进了许多其他可用的遗留部署约定。但是 JAR 文件没有内在的唯一性,除了很少使用的版本号,它隐藏在 .jar 清单中。JAR 文件和可选清单不用作 Java 运行时环境中的模块化约定。因此,文件中类的包名及其在类路径中的参与是 JAR 结构中为运行时环境提供模块化的唯一部分。

简而言之,JAR 是模块化的一次很好的尝试,但它们并不能满足真正模块化环境的所有要求。Spring 和 OSGi 等框架和平台使用 JAR 规范的模式和增强功能来提供构建功能强大的模块化系统的环境。然而,随着时间的推移,即使是这些工具也会屈服于 JAR 规范 JAR 地狱的非常不幸的副作用!

类路径/JAR 地狱

当 Java 运行时环境允许任意复杂的 JAR 加载机制时,开发人员知道他们处于类路径地狱或 JAR 地狱中。许多配置都可能导致这种情况。

首先,考虑这样一种情况,Java 应用程序开发人员提供了应用程序的更新版本,并将其打包在与旧版本名称完全相同的 JAR 文件中。Java 运行时环境不提供用于确定正确 JAR 文件的验证工具。运行时环境将简单地从它首先找到的或满足许多类路径规则之一的 JAR 文件中加载类。这充其量会导致意外行为。

JAR 地狱的另一个例子是两个或多个应用程序或进程依赖于第三方库的不同版本。使用标准的类加载工具,只有一个版本的第三方库在运行时可用,从而导致至少一个应用程序或进程出现错误。

一个功能齐全且高效的 Java 模块系统应该有助于将代码分离为不同的、易于理解且松散耦合的模块。依赖关系应明确指定并严格执行。应该有允许升级模块而不会对其他模块产生负面影响的设施。模块化运行时环境应启用特定于特定领域或垂直市场的配置,从而减少环境的启动时间和系统占用空间。

Java的模块化解决方案

除了到目前为止提到的模块化功能外,最近的努力还增加了一些。以下功能旨在优化性能并支持扩展运行时环境:

分段源代码: 源代码分成不同的缓存段,每个段都包含特定类型的编译代码。其目标包括在垃圾清理、增量构建和更好的内存管理期间跳过非方法代码。

构建时强制: 强制命名空间、版本控制、依赖关系等的语言结构。

部署设施:支持根据特定需求部署扩展的运行时环境,例如移动设备环境

于 2017-08-19T07:27:17.213 回答