包与Java 9中的自动模块冲突

随着Java 9的接近水平,我认为这是一个很好的学习练习,将我的一些项目移植到Java 9.在我的一个项目中,我有依赖关系rxjava和rxjavafx

dependencies { compile 'io.reactivex:rxjava:1.2.6' compile 'io.reactivex:rxjavafx:1.0.0' ... } 

我想创build这个项目作为命名模块。 为此,我需要创build一个module-info.java文件,我需要在这里指定rxjavarxjavafx的需求。 但是,这些库还没有任何模块信息。

为了解决这个问题,我读过我需要创build自动模块 。 从我的理解,我需要重命名rxjavarxjavafxjar子有一个简单的名称,然后列出在--module-path参数中的jar子。 然后我添加一个module-info.java指令在我的module-info.java与jar名称。

 module com.foo.bar { requires rxjavafx; requires rxjava; } 

我写了一个gradle任务来为我编辑jar子名称,而且在大多数情况下它似乎正在工作。 它需要将所有需要编译的jar包重命名为不包含版本信息或斜杠。 这些文件然后连接成一个:分隔的string:

 tasks.withType(JavaCompile) { delete { delete '/tmp/gradle' } copy { from configurations.compile + configurations.testCompile into '/tmp/gradle' rename '(.*)-[0-9]+\\..*.jar', '$1.jar' rename { String fileName -> fileName.replace("-", "") } } options.compilerArgs += ['--module-path', fileTree(dir: '/tmp/gradle', include: '*.jar').getFiles().join(':')] } 

自然, rx库共享一些软件包名称…但是这会导致编译器反吐错误,例如:

 error: module reads package rx.subscriptions from both rxjava and rxjavafx error: module reads package rx.schedulers from both rxjava and rxjavafx error: module reads package rx.observables from both rxjava and rxjavafx error: module rxjava reads package rx.subscriptions from both rxjavafx and rxjava error: module rxjava reads package rx.schedulers from both rxjavafx and rxjava error: module rxjava reads package rx.observables from both rxjavafx and rxjava error: module rxjavafx reads package rx.subscriptions from both rxjava and rxjavafx error: module rxjavafx reads package rx.schedulers from both rxjava and rxjavafx error: module rxjavafx reads package rx.observables from both rxjava and rxjavafx 

似乎解决此问题的唯一方法是将rxjavarxjavafx的内容重新打包到单个jar中,并将其作为单个模块添加。 这似乎不是一个好的解决scheme,但…

所以我的问题是:

  • 我正确使用新的模块系统吗?
  • 我能做些什么关于这个错误? 和
  • 这些依赖关系阻止我更新,还是应该等待rx更新它们的库?

注意:我试着用标准的java / javac运行它,它们导致相同的问题。 另外这里是我的Java版本:

 java version "9-ea" Java(TM) SE Runtime Environment (build 9-ea+140) Java HotSpot(TM) 64-Bit Server VM (build 9-ea+140, mixed mode) 

我正确使用新的模块系统吗?

是。 你所看到的是预期的行为,这是因为JPMS模块不允许拆分包。

如果您不熟悉术语“拆分包”,则意味着来自两个不同模块的相同包中的两个成员。

例如:
com.foo.A(来自moduleA.jar)
com.foo.B(来自moduleB.jar)

我能做些什么关于这个错误?

你有两个select:

  1. (更难)“解开”软件包依赖关系。 然而,如果你不熟悉图书馆的内部工作,这可能是困难的或不可能的
  2. (更简单)将两个瓶子组合成一个jar子(因此也就是一个自动模块),如上所述。 我同意这不是一个“好”的解决scheme,但是首先拆分软件包通常也不是一个好主意。

这些依赖关系阻止我更新,还是应该等待rx更新它们的库?

希望rx最终会在未来的某个时候更新它们的库文件,使其没有拆分包。 在那之前,我的build议是将两个jar子一起粉碎成一个jar子(选项#2)。

我有一个相似的问题:

 error: module flyway.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql error: module slf4j.api reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql error: module hibernate.core reads package javax.transaction.xa from both jboss.transaction.api.1.2.spec and java.sql .../src/main/java/module-info.java:1: error: module eu.com.x reads package javax.transaction.xa from both java.sql and jboss.transaction.api.1.2.spec 

我可以通过检查我的项目传递依赖(“gradle依赖关系”或“mvn依赖:树”可能会有帮助),并通过代码相似排除:

 configurations.all { exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.2_spec' } 

要么

 <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.10.Final</version> <exclusions> <exclusion> <groupId>org.jboss.spec.javax.transaction</groupId> <artifactId>jboss-transaction-api_1.2_spec</artifactId> </exclusion> </exclusions> </dependency> </dependencies> 

我的问题不需要重新包装。 #JDK8上没有发生这个问题。 大概排除依赖并不能帮助每个项目。