资讯专栏INFORMATION COLUMN

Java9模块化学习笔记三之迁移到Java9

NeverSayNever / 2178人阅读

摘要:命令行参数文件鉴于迁移到后可能需要很长的命令行参数,有些会限制命令行长度,支持定义一个命令行参数文件。已有三分库可以自动转成模块,只要在启动时将放在指定路径中,便会自动变成。

java[c]命令行参数文件

鉴于迁移到java9后可能需要很长的命令行参数,有些os会限制命令行长度,java9支持定义一个命令行参数文件。使用方式:

java @arguments.txt

arguments.txt内容(每个选项一行):

-cp application.jar:javassist.jar
--add-opens java.base/java.lang=ALL_UNNAMED
--add-exports java.base/sun.security.x509=ALL_UNNAMED
-jar application.jar
Jdeps

前面我们说过以前很多时候我们或第三方库使用jdk不推荐使用的内部类,比如sun.,jdk.internal.,在jdk9之后这些类被强封装了,为了保持兼容性,默认运行运行时访问,其行为可以通过java选项--illegal-access=值,控制,默认值为permit,其他可选值有warn,debug,deny

除此之外还有些类被移除了,比如sun.misc.Base64Decoder/Base64Encoder, 不过提供了替代方案java.util.Encoder
我们可以借助于jdeps工具来发现这些问题,使用方式:

jdeps -jdkinternals Xxx.class

注意:jdeps只能用于分析class文件或jar,不能用于分析源码文件

使用jdeps分析 classpath-based依赖:
.
├── jars
│ ├── jackson-annotations-2.8.8.jar
│ └── jackson-core-2.8.8.jar
| └── jackson-databind-2.8.8.1.jar
└── out

 ├── demo
     ├── Book.class
     └── Main.class

比如分析上面的这个模块:

jdeps -recursive -summary -cp lib/*.jar out

-recusive代表requires transitive的也会被分析,-summary代表汇总依赖信息,不然会打印很长的依赖信息, -cp classpath, out就是需要被分析的class/jar文件路径

tjw$ jdeps -recursive -summary -cp lib/*.jar out
jackson-annotations-2.8.8.jar -> java.base
jackson-core-2.8.8.jar -> java.base
jackson-databind-2.8.8.jar -> lib/jackson-annotations-2.8.8.jar
jackson-databind-2.8.8.jar -> lib/jackson-core-2.8.8.jar
jackson-databind-2.8.8.jar -> java.base
jackson-databind-2.8.8.jar -> java.desktop
jackson-databind-2.8.8.jar -> java.logging
jackson-databind-2.8.8.jar -> java.sql
jackson-databind-2.8.8.jar -> java.xml
out -> lib/jackson-databind-2.8.8.jar
out -> java.base

上面的依赖分析显示,我们的代码直接依赖jackson-databind,故而我们在迁移到模块时应将jackson-databind作为Automic Module,故而迁移到模块化后的代码结构如下:
.
├── lib
│ ├── jackson-annotations-2.8.8.jar
│ └── jackson-core-2.8.8.jar
├── mods
│ └── jackson-databind-2.8.8.jar //这里会被作为Automic Module
└── src

└── books
    ├── demo
    │   ├── Book.java
    │   └── Main.java
    └── module-info.java

module-info.java内容:

module books {
    requires jackson.databind;
    opens demo;
}

使用jdeps分析 module-based依赖:
jdeps -module-path out:mods -m books

注意:使用jdeps我们还可以利用-dotoutput选项来输出模块的依赖关系图作为文件保存

除了分析依赖之外,jdeps还可以生成module-info.java,这在迁移已有三方库的时候特别有用:

jdeps --generate-module-info ./out mylibrary.jar
JAXB与其他JavaEE API

java.se.ee模块

Automatic Modules

除了之前说的unamed modules,还有一种叫automatic modules,这是为解决已有三方库迁移到模块化的问题。已有三分库可以自动转成模块,只要在启动时将jar放在指定--module-path路径中,便会自动变成automatic module。
automatic module的特性:1、该module本身是open的;2、该module的依赖由开发者自行解决,编译时无法找出相关问题;3、automatic module与explicit module的区别在于,前者可以无限制访问unamed module,而后者遵循模块的封装性原则。
automatic modules模块名: 比如jackson-databind-2.8.8.jar,在java定义它成模块时,首先需要扫描MATA-INF/MANIFEST.MF中的Automatic-Module-Name字段,如果没有这个字段,那么就以jar文件名字作为模块名,比如jackson-databind-2.8.8.jar的模块名就是jackson.databind,转成模块名时会把-替换成. 然后版本号会被忽略掉。

迁移示例:迁移Spring And Hibernate

未迁移代码就不列出来了,迁移后的代码结构如下:

.
├── README.md
├── lib
│   ├── hsqldb-2.3.4.jar
│   ├── ...
│   ├── slf4j-api-1.7.21.jar
│   ├── slf4j-simple-1.7.21.jar
│   ├── spring-aop-4.3.2.RELEASE.jar
│   ├── spring-beans-4.3.2.RELEASE.jar
│   ├── spring-core-4.3.2.RELEASE.jar
│   ├── spring-expression-4.3.2.RELEASE.jar
│   ├── spring-jdbc-4.3.2.RELEASE.jar
│   └── spring-orm-4.3.2.RELEASE.jar
├── mods
│   ├── hibernate-core-5.2.2.Final.jar
│   ├── hibernate-jpa-2.1-api-1.0.0.Final.jar
│   ├── javassist-3.20.0-GA.jar
│   ├── javax.inject-1.jar
│   ├── spring-context-4.3.2.RELEASE.jar
│   └── spring-tx-4.3.2.RELEASE.jar
├── run.sh
└── src
    └── bookapp
        ├── books
        │   ├── api
        │   │   ├── entities
        │   │   │   └── Book.java
        │   │   └── service
        │   │       └── BooksService.java
        │   └── impl
        │       ├── entities
        │       │   └── BookEntity.java
        │       └── service
        │           └── HibernateBooksService.java
        ├── bookstore
        │   ├── api
        │   │   └── service
        │   │       └── BookstoreService.java
        │   └── impl
        │       └── service
        │           └── BookstoreServiceImpl.java
        ├── log4j2.xml
        ├── main
        │   └── Main.java
        ├── main.xml
        └── module-info.java

module-info.java内容

module bookapp {
    requires spring.context;
    requires spring.tx;

    requires javax.inject;

    requires hibernate.core;
    requires hibernate.jpa;

    exports books.api.entities;
    exports books.api.service;
    opens books.impl.entities;
    opens books.impl.service;

    exports bookstore.api.service;
    opens bookstore.impl.service;
}

run.sh内容

CP=lib/antlr-2.7.7.jar:
...
CP+=lib/slf4j-api-1.7.21.jar:
CP+=lib/slf4j-simple-1.7.21.jar:
CP+=lib/spring-aop-4.3.2.RELEASE.jar:
CP+=lib/spring-beans-4.3.2.RELEASE.jar:
CP+=lib/spring-core-4.3.2.RELEASE.jar:
CP+=lib/spring-expression-4.3.2.RELEASE.jar:
CP+=lib/spring-jdbc-4.3.2.RELEASE.jar:
CP+=lib/spring-orm-4.3.2.RELEASE.jar

$JAVA_HOME/bin/javac -cp $CP 
      --module-path mods 
      --add-modules java.naming 
      -d out         
      --module-source-path src 
      -m bookapp

cp $(find src -name "*.xml") out/bookapp

$JAVA_HOME/bin/java -cp $CP 
     --module-path mods:out       
     --add-modules java.xml.bind,java.sql 
     --add-opens java.base/java.lang=javassist 
     -m bookapp/main.Main

我们还可以将自己的应用拆分为多个模块
演化图如下:


迁移Library到模块化

迁移方式一,迁移为Automatic Module,适用于没有源码的情形:
模块名:在MANIFEST.MF中定义

Automatic-Module-Name: com.javamodularity.modulename
jar -cfm mylibrary.jar META-INF/MANIFEST.MF -C out/ .

你也可以使用maven插件


    org.apache.maven.plugins
    maven-jar-plugin
    
        
            
                com.mymodule
            
        
    

迁移方式二,迁移为explicit module,适用于库的作者或者有源码的情形:
首先借助jdeps生成module-info.java,然后进行简单修改

jdeps --generate-module-info ./out mylibrary.jar  //你也可以使用--generate-open-module选项

方式三,迁移为explicit module,即使没有源码:

mkdir mylibrary
cd mylibrary
jar -xf ../mylibrary.jar
cd ..
javac -d mylibrary out/mylibrary/module-info.java
jar -uf mylibrary.jar -C mylibrary module-info.class

针对不同版本发布 javac --release 版本号 比如 javac --release 8

模块化开发工具 maven
.
├── README.md
├── algorithm.api
│   ├── pom.xml
│   └── src
│       └── main
│           └── java
│               ├── javamodularity
│               │   └── easytext
│               │       └── algorithm
│               │           └── api
│               │               ├── Analyzer.java
│               │               ├── Preprocessing.java
│               │               └── SyllableCounter.java
│               └── module-info.java
├── cli
│   ├── README.adoc
│   ├── pom.xml
│   └── src
│       └── main
│           ├── java
│           │   ├── javamodularity
│           │   │   └── easytext
│           │   │       └── cli
│           │   │           └── Main.java
│           │   └── module-info.java
│           └── resources
│               └── test.txt
├── gui
│   ├── gui.iml
│   ├── pom.xml
│   └── src
│       └── main
│           └── java
│               ├── javamodularity
│               │   └── easytext
│               │       └── gui
│               │           └── Main.java
│               └── module-info.java
├── pom.xml
└── run.sh

      
        
          org.apache.maven.plugins
          maven-compiler-plugin
          3.6.1
          
            9
          
        
      

使用maven执行模块

  
    
      
        org.codehaus.mojo
        exec-maven-plugin
        1.6.0
        
          
            
              exec
            
          
        
        
          ${JAVA_HOME}/bin/java
          
            --module-path
            
            --module
            easytext.cli/javamodularity.easytext.cli.Main
            ${easytext.file}
          
        
      
    
  

具体执行命令 mvn exec:exec

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71471.html

相关文章

  • Java9的新特性

    摘要:新特性概述系列一安装及使用系列二运行系列三模块系统精要系列四更新系列五系列六系列七系列八系列九与的区别迁移注意事项参数迁移相关选项解析使用构建实例使用示例带你提前了解中的新特性 Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13的新特性...

    ddongjian0000 评论0 收藏0
  • Java9块化学习笔记二之模块设计模式

    摘要:但是模块化当中,无法扫描只有模块中可以使用有两种解决方案定义一个专门的资源模块,并使用提供的接口,实现它,并将这个实现注册为服务。有两种方式使用或包名,包名模块名使用运行时动态。 模块设计的原则: 1、防止出现编译时循环依赖(主要是编译器不支持),但运行时是允许循环依赖的,比如GUI应用2、明确模块的边界 几种模块设计: API模块,聚合模块(比如java.base) 可选依赖 两种方...

    李文鹏 评论0 收藏0
  • Java9块化学习笔记一之快速入门

    摘要:如果你想查看运行时模块的加载过程输出结果表示为模块,由于我限制了不再往下输出了,而我们模块又没有别的额外依赖,所以仅有这行输出。 jdk9模块快速入门 列出自带模块:java --list-modulesmac多版本jdk共存:http://adolphor.com/blog/2016...模块规则示意图:showImg(https://segmentfault.com/img/bVb...

    cjie 评论0 收藏0
  • java9 gc log参数迁移

    摘要:序本文主要研究一下参数的迁移。比如实例为,为,文件数为,每个文件,文件名为,为和输出实例迁移旧版相关参数迁移旧版运行时参数迁移小结把的配置统一到了中,可以按照官方给出的新旧参数映射表进行迁移。 序 本文主要研究一下java9 gc log参数的迁移。 统一JVM及GC的Logging java9引进了一个统一的日志框架,对gc log的输出进行了统一的配置。 相关JEP(JDK Enh...

    Kahn 评论0 收藏0
  • Java9特性预览——Jshell

    摘要:什么是项目是第一个官方的的缩写,即交互式编程环境,是一种命令行工具。它允许你无需编写类或者方法来执行语句。它与的解释器或其它本地支持的语言,如和类似。在即将到来的的特性中,这绝对是更有趣的特性之一。 什么是JShell? JShell/Kulla项目是第一个官方的Java REPL (Read-Eval-Print-Loop的缩写,即交互式编程环境),是一种命令行工具。它允许你无需编写...

    hikui 评论0 收藏0

发表评论

0条评论

NeverSayNever

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<