Java 9:将自定义模块化运行时映像与第三方插件系统相结合



根据Mark Reinhold的Twitter帖子,我假设Jigsaw将成为Java 9的一部分。

在阅读有关 Jigsaw 的信息时,我问自己一个问题:当我使用自定义模块化运行时映像发布应用程序,但第三方模块需要其他 JRE 模块时会发生什么情况,这些模块未随应用程序一起发布,因为它们不是应用程序需要的?

想象一下,一个应用程序希望从模块化中受益。它提供了一个可由第三方模块实现的服务接口。应用程序加载所有第三方模块,这些模块在应用程序启动时提供服务接口的实现。在我看来,这是为第三方插件提供公共 API 的一种伟大而简单的方法,我可以想象自己经常使用它。

现在,还有一个名为jlink的工具,它允许人们创建应用程序的发布,该应用程序不仅包含应用程序模块,还包含所需的JRE模块。这称为自定义模块化运行时映像。最棒的是,该版本仅包含应用程序实际使用的 JRE 模块,这可以防止发布变得非常大。目前,jlink将确定必须自行包含哪些模块。但是,提供模块的服务实现必须由开发人员显式包含,请参阅此处。我认为这对于开发人员不希望要求用户安装 JRE 的许多应用程序也非常有用。

当我们尝试在单个应用程序中同时使用两者时,就会出现问题:自定义模块化运行时映像仅包含应用程序使用的 JRE 模块。但是,插件可能使用应用程序尚未使用的 JRE 模块,因此这些模块在运行时不可用。因此,该插件将无法工作。


这是我能想到的唯一解决方案,但它远非完美:

将缺少的 JRE 模块包含在第三方插件中。虽然乍一看这似乎是一个简单的解决方案,但实际上它带来了很多问题。

首先,这要求插件开发人员知道应用程序中包含哪些 JRE 模块。如果这是未知的,它们可能包含应用程序本身中已经可用的 JRE 模块,这可能会导致问题。因此,它成为应用程序使用哪些模块的公共 API 的一部分。我认为这是不可取的,因为它是一个实现细节。此外,它可能会经常更改。

其次,由于可用的 JRE 模块是公共 API 的一部分,因此需要以某种方式指定它们。虽然这可以通过文档工作,但我认为它应该通过正式代码指定。例如,在应用程序模块中对所有 JRE 模块使用 requires public 子句可能会起作用,这些模块应该可用于插件模块。这使得这些 JRE 模块可供插件使用,因为插件将require应用程序模块。

第三,问题出现了,是否允许插件使用额外的 JRE 模块。如果不是,则module-info.java可能应该有一个子句来指定当前模块是给定其他模块的插件。例如,与其对应用程序模块使用 require,不如使用 plugs in to 或其他表示法。这将防止模块需要任何 JRE 模块。但是,这可能行不通,因为插件模块所需的其他第三方模块可能需要额外的 JRE 模块。因此,我认为很难为这种机制提供支持。

第四,也很难允许插件使用额外的 JRE 模块。这要么要求不同的 JRE 模块在不同版本中兼容,要么插件开发人员始终将其他 JRE 模块包含在与应用程序中的 JRE 模块版本兼容的版本中。我不确定 JRE 模块是否应该在不同版本中兼容,但我的假设是它们不应该兼容,因为它会阻止将来的许多更改。

我的一些假设是错误的吗?也许在应用程序和插件中包含 JRE 模块就可以了?也许插件中的附加 JRE 模块也不必与应用程序中的 JRE 模块兼容?毕竟,它们可能不会相互交流。


我们应该如何处理这个架构问题?是否有其他语言具有模块化和部分可发布的运行时?他们是如何解决问题的?

请注意,谷歌番石榴或 Apache 共享资源等常用库可能会出现类似的问题。但是,这个问题应该主要是关于使用自定义模块化运行时映像引起的问题。

我有完全相同的想法,并考虑了几天。这个问题似乎没有任何好的资源。我的想法是一个自定义框架。该框架可以允许第三方模块使用配置文件请求其他依赖项模块。然后,框架将决定是否(可以通过用户交互完成(模块是否将安装到应用程序中。JRE 模块可以直接安装到 JRE 模块文件夹中,其他模块可以复制到自定义文件夹中,以便于维护。但是这个解决方案需要一些来自Oracle的端点,允许开发人员下载单个jmod文件。

最新更新