鑑於遷移到java9後可能須要很長的命令行參數,有些os會限制命令行長度,java9支持定義一個命令行參數文件。使用方式:java
java @arguments.txt
arguments.txt內容(每一個選項一行):spring
-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
前面咱們說過之前不少時候咱們或第三方庫使用jdk不推薦使用的內部類,好比sun.,jdk.internal.,在jdk9以後這些類被強封裝了,爲了保持兼容性,默認運行運行時訪問,其行爲能夠經過java選項--illegal-access=值,控制,默認值爲permit,其餘可選值有warn,debug,denysql
除此以外還有些類被移除了,好比sun.misc.Base64Decoder/Base64Encoder, 不過提供了替代方案java.util.Encoder
咱們能夠藉助於jdeps
工具來發現這些問題,使用方式:express
jdeps -jdkinternals Xxx.class
注意:jdeps只能用於分析class文件或jar,不能用於分析源碼文件apache
使用jdeps分析 classpath-based依賴:
.
├── jars
│ ├── jackson-annotations-2.8.8.jar
│ └── jackson-core-2.8.8.jar
| └── jackson-databind-2.8.8.1.jar
└── outapi
├── demo ├── Book.class └── Main.class
好比分析上面的這個模塊:app
jdeps -recursive -summary -cp lib/*.jar out
-recusive表明requires transitive的也會被分析,-summary表明彙總依賴信息,否則會打印很長的依賴信息, -cp classpath, out就是須要被分析的class/jar文件路徑maven
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
java.se.ee模塊
除了以前說的unamed modules,還有一種叫automatic modules,這是爲解決已有三方庫遷移到模塊化的問題。已有三分庫能夠自動轉成模塊,只要在啓動時將jar放在指定--module-path路徑中,便會自動變成automatic module。
automatic module的特性:一、該module自己是open的;二、該module的依賴由開發者自行解決,編譯時沒法找出相關問題;三、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,轉成模塊名時會把-
替換成.
而後版本號會被忽略掉。
未遷移代碼就不列出來了,遷移後的代碼結構以下:
. ├── 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
咱們還能夠將本身的應用拆分爲多個模塊
演化圖以下:
遷移方式一,遷移爲Automatic Module,適用於沒有源碼的情形:
模塊名:在MANIFEST.MF中定義
Automatic-Module-Name: com.javamodularity.modulename
jar -cfm mylibrary.jar META-INF/MANIFEST.MF -C out/ .
你也可使用maven插件
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <Automatic-Module-Namec>com.mymodule</Automatic-Module-Name> </manifestEntries> </archive> </configuration> </plugin>
遷移方式二,遷移爲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
. ├── 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
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <release>9</release> </configuration> </plugin> </plugins> </build>
使用maven執行模塊
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.6.0</version> <executions> <execution> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>${JAVA_HOME}/bin/java</executable> <arguments> <argument>--module-path</argument> <modulepath/> <argument>--module</argument> <argument>easytext.cli/javamodularity.easytext.cli.Main</argument> <argument>${easytext.file}</argument> </arguments> </configuration> </plugin> </plugins> </build>
具體執行命令 mvn exec:exec