包与 Java 9 中的自动模块冲突
Package conflicts with automatic modules in Java 9
随着 Java 9 的临近,我认为将我的一些项目移植到 Java 9 将是一个很好的学习练习。在我的一个项目中,我依赖于 rxjava and rxjavafx
dependencies {
compile 'io.reactivex:rxjava:1.2.6'
compile 'io.reactivex:rxjavafx:1.0.0'
...
}
我想将此项目创建为命名模块。为此,我需要创建一个 module-info.java
文件,并且需要在此处指定 rxjava
和 rxjavafx
的要求。但是,这些库还没有任何模块信息。
为了解决这个问题,我阅读了 I need to create Automatic Modules。据我了解,我需要将 rxjava
和 rxjavafx
罐重命名为一个简单的名称,然后在 --module-path
参数中列出这些罐。然后我在我的 module-info.java
中添加一个 requires
指令和 jar 名称。
module com.foo.bar {
requires rxjavafx;
requires rxjava;
}
我写了一个 gradle 任务来为我编辑 jar 名称,它似乎在大多数情况下都有效。它获取所有需要编译的 jar 并将它们重命名为不包含版本信息或斜杠。然后将文件连接成 :
分隔的字符串:
tasks.withType(JavaCompile) {
delete { delete '/tmp/gradle' }
copy {
from configurations.compile + configurations.testCompile
into '/tmp/gradle'
rename '(.*)-[0-9]+\..*.jar', '.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 中,并将其作为一个模块添加。不过,这似乎不是一个好的解决方案...
所以我的问题是:
- 我是否正确使用了新的模块系统?
- 我该如何处理这个错误?和
- 这些依赖项会阻止我更新吗,还是我应该等待 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)
Am I using the new module system correctly?
是的。您看到的是预期行为,这是因为 JPMS 模块不允许拆分包。
如果您不熟悉术语 "split packages",它本质上是指来自两个不同模块的同一包的两个成员。
例如:
com.foo.A(来自moduleA.jar)
com.foo.B(来自moduleB.jar)
What can I do about this error?
您有两个选择:
- (更难)"unsplit" 包依赖项。然而,如果您不熟悉库的内部运作,这可能会很困难或不可能
- (更容易)将两个罐子组合成一个罐子(因此是一个自动模块),如上所述。我同意这不是 "good" 解决方案,但首先拆分包通常也不是一个好主意。
Do these dependencies prevent me from updating, or should I just wait for rx to update their libs?
希望 rx 最终会更新他们的库,以便在将来的某个时候没有拆分包。在那之前,我的建议是将两个罐子一起粉碎成一个罐子(选项 #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 dependencies" 或 "mvn dependency:tree" 可能会有帮助)并通过类似于以下的代码排除来摆脱拆分包编译问题:
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>
我的问题不需要重新打包 jar。 #JDK8 上没有出现这个问题。排除依赖项可能对每个项目都没有帮助。
我一直面临与 java.transaction.xa 从 javaee 和 java.transaction.xa 读取包的相同问题。
我通过将此行添加到我的模块-info.java
来修复它
opens javax.transaction.xa;
它工作正常,但出现提示说包 javax.transaction.xa 为空或不存在。但是源代码编译正确。
随着 Java 9 的临近,我认为将我的一些项目移植到 Java 9 将是一个很好的学习练习。在我的一个项目中,我依赖于 rxjava and rxjavafx
dependencies {
compile 'io.reactivex:rxjava:1.2.6'
compile 'io.reactivex:rxjavafx:1.0.0'
...
}
我想将此项目创建为命名模块。为此,我需要创建一个 module-info.java
文件,并且需要在此处指定 rxjava
和 rxjavafx
的要求。但是,这些库还没有任何模块信息。
为了解决这个问题,我阅读了 I need to create Automatic Modules。据我了解,我需要将 rxjava
和 rxjavafx
罐重命名为一个简单的名称,然后在 --module-path
参数中列出这些罐。然后我在我的 module-info.java
中添加一个 requires
指令和 jar 名称。
module com.foo.bar {
requires rxjavafx;
requires rxjava;
}
我写了一个 gradle 任务来为我编辑 jar 名称,它似乎在大多数情况下都有效。它获取所有需要编译的 jar 并将它们重命名为不包含版本信息或斜杠。然后将文件连接成 :
分隔的字符串:
tasks.withType(JavaCompile) {
delete { delete '/tmp/gradle' }
copy {
from configurations.compile + configurations.testCompile
into '/tmp/gradle'
rename '(.*)-[0-9]+\..*.jar', '.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 中,并将其作为一个模块添加。不过,这似乎不是一个好的解决方案...
所以我的问题是:
- 我是否正确使用了新的模块系统?
- 我该如何处理这个错误?和
- 这些依赖项会阻止我更新吗,还是我应该等待 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)
Am I using the new module system correctly?
是的。您看到的是预期行为,这是因为 JPMS 模块不允许拆分包。
如果您不熟悉术语 "split packages",它本质上是指来自两个不同模块的同一包的两个成员。
例如:
com.foo.A(来自moduleA.jar)
com.foo.B(来自moduleB.jar)
What can I do about this error?
您有两个选择:
- (更难)"unsplit" 包依赖项。然而,如果您不熟悉库的内部运作,这可能会很困难或不可能
- (更容易)将两个罐子组合成一个罐子(因此是一个自动模块),如上所述。我同意这不是 "good" 解决方案,但首先拆分包通常也不是一个好主意。
Do these dependencies prevent me from updating, or should I just wait for rx to update their libs?
希望 rx 最终会更新他们的库,以便在将来的某个时候没有拆分包。在那之前,我的建议是将两个罐子一起粉碎成一个罐子(选项 #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 dependencies" 或 "mvn dependency:tree" 可能会有帮助)并通过类似于以下的代码排除来摆脱拆分包编译问题:
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>
我的问题不需要重新打包 jar。 #JDK8 上没有出现这个问题。排除依赖项可能对每个项目都没有帮助。
我一直面临与 java.transaction.xa 从 javaee 和 java.transaction.xa 读取包的相同问题。 我通过将此行添加到我的模块-info.java
来修复它 opens javax.transaction.xa;
它工作正常,但出现提示说包 javax.transaction.xa 为空或不存在。但是源代码编译正确。