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

fla*_*kes 27 java compiler-errors java-platform-module-system java-9

随着Java 9的出现,我认为将我的一些项目移植到Java 9是一个很好的学习练习.在我的一个项目中,我有rxjavarxjavafx的依赖

dependencies {
    compile 'io.reactivex:rxjava:1.2.6'
    compile 'io.reactivex:rxjavafx:1.0.0'
    ...
}
Run Code Online (Sandbox Code Playgroud)

我想将此项目创建为命名模块.要做到这一点,我需要创建一个module-info.java文件,我需要指定的要求rxjava,并rxjavafx在这里.但是,这些库还没有任何模块信息.

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

module com.foo.bar {
    requires rxjavafx;
    requires rxjava;
}
Run Code Online (Sandbox Code Playgroud)

我编写了一个gradle任务来为我编辑jar名称,它似乎在大多数情况下都有效.它需要编译所有的jar并将它们重命名为不包含version-info或slashes.然后将这些文件连接成一个:单独的字符串:

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(':')]
}
Run Code Online (Sandbox Code Playgroud)

当然,这些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
Run Code Online (Sandbox Code Playgroud)

这似乎是唯一的办法来解决这个问题将是重新包装的内容rxjavarxjavafx成一个单一的罐子,并添加作为一个单独的模块.这似乎不是一个好的解决方案......

所以我的问题是:

  • 我正确使用新模块系统吗?
  • 我该怎么办这个错误?和
  • 这些依赖项是否阻止我更新,或者我应该等待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)
Run Code Online (Sandbox Code Playgroud)

And*_*ert 20

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

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

如果您不熟悉术语"拆分包",它实质上意味着来自两个不同模块的同一包的两个成员.

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

我该怎么办这个错误?

您有两种选择:

  1. (更难)"unsplit"包依赖.但是,如果您不熟悉库的内部工作原理,这可能很难或不可能
  2. (更容易)如上所述,将两个罐子组合成一个罐子(因此是一个自动模块).我同意这不是一个"好"的解决方案,但首先分开包装通常也不是一个好主意.

这些依赖项是否阻止我更新,或者我应该等待rx更新它们的库?

希望rx最终会更新他们的库,以便在将来的某个时候没有拆分包.在那之前,我的建议是将两个罐子一起粉碎成一个罐子(选项#2).

  • @eugcomax重要的是要注意JDK 9迁移有两个不同的阶段 - 1)"容忍"java 9(即运行应用程序作为未命名的模块)然后2)"采用"java 9(即将应用程序转换为使用模块) -info,所以他们被命名为模块).我相信第一阶段不太可能破坏人们的代码,但第二阶段无疑将是一个令人头痛的问题. (6认同)
  • 是的,这是一个痛苦,但afaik有安全+性能优势,不允许拆分包.希望lib所有者能够快速提供组合罐.或者我可以看到maven central提供自动组合罐. (4认同)
  • 阅读java 9迁移说明很有趣,jdk9很可能会破坏你的代码.但这种限制打破了大量的图书馆.对于通过多个jar分发的库,拆分包是一种非常常见的做法. (3认同)
  • 您可能正在使用非常旧的JDK构建.jsr305注释现在已经在他们自己的模块中一段时间​​了,它不包含在java.se聚合模块中.因此默认情况下,此模块不会添加到JDK中. (3认同)
  • 您可以将两个 jar 解压缩到同一个目录中,然后将它们压缩回一个存档(并将文件扩展名从 .zip 重命名为 .jar) (2认同)

Rad*_*ski 5

我有类似的问题:

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
Run Code Online (Sandbox Code Playgroud)

我可以通过检查我的项目传递依赖项(“gradle 依赖项”或“mvn 依赖项:树”可能会有所帮助)并通过类似于以下内容的代码排除来解决拆分包编译问题:

configurations.all {
    exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.2_spec'
}
Run Code Online (Sandbox Code Playgroud)

或者

<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>
Run Code Online (Sandbox Code Playgroud)

我的问题不需要 jar 重新包装。#JDK8 上未出现此问题。可能排除依赖项对每个项目都没有帮助。