包与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
文件,我需要在这里指定rxjava
和rxjavafx
的需求。 但是,这些库还没有任何模块信息。
为了解决这个问题,我读过我需要创build自动模块 。 从我的理解,我需要重命名rxjava
和rxjavafx
jar子有一个简单的名称,然后列出在--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
似乎解决此问题的唯一方法是将rxjava
和rxjavafx
的内容重新打包到单个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:
- (更难)“解开”软件包依赖关系。 然而,如果你不熟悉图书馆的内部工作,这可能是困难的或不可能的
- (更简单)将两个瓶子组合成一个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上没有发生这个问题。 大概排除依赖并不能帮助每个项目。