当前位置: 首页 > 工具软件 > Jigsaw > 使用案例 >

java jigsaw_java - 为什么要项目Jigsaw / JPMS?

璩俊雅
2023-12-01

为了论证,让我们断言Java 8(及更早版本)已经有模块(jar)和模块系统(类路径)的“形式”。 但是这些都存在众所周知的问题。

通过检查问题,我们可以说明Jigsaw的动机。 (以下假设我们没有使用OSGi,JBoss模块等,它们肯定会提供解决方案。)

问题1:公众过于公开

考虑以下类(假设两者都是公共的):

com.acme.foo.db.api.UserDao

com.acme.foo.db.impl.UserDaoImpl

在Foo.com,我们可能会决定我们的团队应该使用foo-app.jar而不是直接使用foo-services.jar。 但是,没有办法在类路径上强制执行该操作。

在Jigsaw中,模块包含一个foo-app.jar文件,该文件允许我们明确说明对其他模块的公共内容。 也就是说,公众有细微差别。 例如:

// com.acme.foo.db.api.UserDao is accessible, but

// com.acme.foo.db.impl.UserDaoImpl is not

module com.acme.foo.db {

exports com.acme.foo.db.api;

}

问题2:反思是肆无忌惮的

鉴于#1中的类,有人仍然可以在Java 8中执行此操作:

Class c = Class.forName("com.acme.foo.db.impl.UserDaoImpl");

Object obj = c.getConstructor().newInstance();

也就是说:反射是强大且必不可少的,但如果不加以控制,它可以用于以不合需要的方式进入模块的内部。 马克莱因霍尔德有一个相当惊人的例子。 (SO帖子在这里。)

在Jigsaw中,强大的封装提供了拒绝访问类的能力,包括反射。 (这可能取决于命令行设置,等待JDK 9的修订技术规范。)请注意,因为Jigsaw用于JDK本身,Oracle声称这将允许Java团队更快地创新平台内部。

问题3:类路径消除了架构关系

团队通常有关于罐子之间关系的心理模型。 例如,foo-app.jar可能使用foo-services.jar,它使用foo-db.jar.我们可能断言bar-lib-1.1.jar中的类不应绕过“服务层”并直接使用bar-lib-2.2.jar。 但是,没有办法通过类路径强制执行。 Mark Reinhold在这里提到了这一点。

相比之下,Jigsaw为模块提供了明确,可靠的可访问性模型。

问题4:单片运行时

Java运行时是单片bar-lib-1.1.jar.在我的机器上,它是60+ MB,20k类! 在微服务,物联网设备等时代,如果不使用Corba,Swing,XML和其他库,则不希望在磁盘上使用它们。

Jigsaw将JDK本身分解为许多模块; 例如 java.sql包含熟悉的SQL类。 这有几个好处,但新的是bar-lib-1.1.jar工具。 假设应用程序完全模块化,bar-lib-2.2.jar生成可分发的运行时映像,该映像被修剪为仅包含指定的模块(及其依赖项)。 展望未来,Oracle设想未来将JDK模块提前编译为本机代码。 尽管jlink是可选的,并且AOT编译是实验性的,但它们是Oracle前进的主要指标。

问题5:版本控制

众所周知,类路径不允许我们使用相同jar的多个版本:例如 bar-lib-1.1.jar和bar-lib-2.2.jar。

Jigsaw没有解决这个问题; 马克莱因霍尔德说明了这里的理由。 要点是Maven,Gradle和其他工具代表了依赖管理的大型生态系统,而另一种解决方案将更有害而不是有益。

应该注意的是,其他解决方案(例如OSGi)确实解决了这个问题(除了#4之外的其他解决方案)。

底线

这是Jigsaw的一些关键点,受特定问题的驱动。

请注意,解释Jigsaw,OSGi,JBoss Modules等之间的争议是一个单独的讨论,属于另一个Stack Exchange站点。 解决方案之间的差异比此处描述的要多得多。 此外,还有足够的共识来批准JSR 376的公众评论复议投票。

 类似资料: