博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java9系列(八)Multi-Release JAR Files
阅读量:5999 次
发布时间:2019-06-20

本文共 6983 字,大约阅读时间需要 23 分钟。

本文主要研究下

multi-release jar (MR JAR)

java9新支持了multi-release jar的功能,包括jar、javac、javap、jdeps等命令都能支持这个特性。所谓multi-release jar可以包含多个jdk版本的实现,在运行时JVM根据当前环境加载符合版本的class,这样可以使得jar包在兼容旧版本的同时尽可能早地尝试新版JDK的特性。

通过--release参数指定编译版本,依赖 来编译成指定JDK版本的class

具体的变化就是META-INF目录下MANIFEST.MF文件新增了一个属性:

Multi-Release: true

然后META-INF目录下还新增了一个versions目录,如果是要支持java9,则在versions目录下有9的目录

实例

java8

  • com.example.lang
public class StackHelper {    public static String getCurrentStack() {        System.out.println("java 8 stack");        return Arrays.stream(Thread.currentThread()                .getStackTrace())                .map(element -> element.toString())                .collect(Collectors.joining("\n"));    }}
  • maven
com.example
mr-jar-java
UTF-8
1.8
1.8
com.example
mr-jar-java9
0.0.1-SNAPSHOT
provided
org.apache.maven.plugins
maven-jar-plugin
${project.artifactId}
${project.artifactId}
${project.version}
true
org.apache.maven.plugins
maven-dependency-plugin
add-java9-classes
generate-resources
unpack-dependencies
com.example
mr-jar-java9
true
${project.build.directory}/generated-resources/META-INF/versions/9
**/*.class
org.codehaus.mojo
build-helper-maven-plugin
3.0.0
add-resource
generate-resources
add-resource
${project.build.directory}/generated-resources/
注意,这里依赖java9的jar包,然后Multi-Release设置为true,通过编译打包把java9的classes放到META-INF/versions/9目录下,原来java8的classes位置不变。

java9

  • com.example.lang
public class StackHelper {    public static String getCurrentStack() {        System.out.println("java 9 stack");        return StackWalker.getInstance()                .walk(frames -> frames.map(Object::toString)                        .collect(joining("\n")));    }}
  • module-info.java
module mr.jar.java9 {    exports com.example.lang;}
  • maven
com.example
mr-jar-java9
UTF-8
9
9
org.apache.maven.plugins
maven-compiler-plugin
3.6.2
9

打包

mvn clean install
  • jar包内容如下
➜  mr-jar-java-0.0.1-SNAPSHOT git:(master) ✗ tree.├── META-INF│   ├── MANIFEST.MF│   ├── maven│   │   └── com.example│   │       └── mr-jar-java│   │           ├── pom.properties│   │           └── pom.xml│   └── versions│       └── 9│           ├── com│           │   └── example│           │       └── lang│           │           ├── StackHelper.class│           │           └── StringHelper.class│           └── module-info.class└── com    └── example        └── lang            ├── StackHelper.class            └── StringHelper.class12 directories, 8 files
  • 查看MANIFEST.MF
Manifest-Version: 1.0Created-By: Apache Maven 3.3.3Built-By: demoBuild-Jdk: 9Implementation-Title: mr-jar-javaImplementation-Version: 0.0.1-SNAPSHOTMulti-Release: trueSpecification-Title: mr-jar-java
  • 确认java8 class版本
➜  mr-jar-java-0.0.1-SNAPSHOT git:(master) ✗ javap -verbose ./com/example/lang/StackHelper.classClassfile /Users/demo/multi-release-jar-demo/mr-jar-java8/target/mr-jar-java-0.0.1-SNAPSHOT/com/example/lang/StackHelper.class  Last modified 2018年3月7日; size 1901 bytes  MD5 checksum 9fafe51ca3df481e8c2264753c281a9a  Compiled from "StackHelper.java"public class com.example.lang.StackHelper  minor version: 0  major version: 52  flags: (0x0021) ACC_PUBLIC, ACC_SUPER  this_class: #15                         // com/example/lang/StackHelper  super_class: #16                        // java/lang/Object  interfaces: 0, fields: 0, methods: 3, attributes: 3
可以看到major版本是52
  • 确认java9 class版本
➜  mr-jar-java-0.0.1-SNAPSHOT git:(master) ✗ javap -verbose ./META-INF/versions/9/com/example/lang/StackHelper.classClassfile /Users/demo/multi-release-jar-demo/mr-jar-java8/target/mr-jar-java-0.0.1-SNAPSHOT/META-INF/versions/9/com/example/lang/StackHelper.class  Last modified 2018年3月7日; size 1921 bytes  MD5 checksum da6326681eb1b0584998a92178e22e27  Compiled from "StackHelper.java"public class com.example.lang.StackHelper  minor version: 0  major version: 53  flags: (0x0021) ACC_PUBLIC, ACC_SUPER  this_class: #14                         // com/example/lang/StackHelper  super_class: #15                        // java/lang/Object  interfaces: 0, fields: 0, methods: 3, attributes: 3
可以看到major版本是53

运行

  • java8
java 8 stackjava.lang.Thread.getStackTrace(Thread.java:1559)com.example.lang.StackHelper.getCurrentStack(StackHelper.java:14)Java8Main.main(Java8Main.java:15)
  • java9
java 9 stackmr.jar.java9/com.example.lang.StackHelper.getCurrentStack(StackHelper.java:13)mr.jar.java9.main/mr.jar.java9.main.Java9Main.main(Java9Main.java:17)
注意java9调用multi-release jar的工程,需要requires该module,然后编译运行都需要添加module-path
java --module-path ./target/classes:/Users/demo/.m2/repository/com/example/mr-jar-java/0.0.1-SNAPSHOT/mr-jar-java-0.0.1-SNAPSHOT.jar --module mr.jar.java9.main/mr.jar.java9.main.Java9Main

jar命令

上面的例子是利用maven插件来打包,也可以使用jar来打包multi-release jar,实例如下:

javac --release 8 -d out/8 mr-jar-java8/src/main/java/com/example/lang/StackHelper.javajavac --release 9 -d out/9 mr-jar-java9/src/main/java/com/example/lang/StackHelper.javajar -cfm out/mr-jar-demo.jar ./MANIFEST.MF -C out/8 .jar -uf out/mr-jar-demo.jar --release 9 -C out/9 .
这里的-c表示创建jar包,-C表示转去该目录执行不带-C的jar命令,-f指定jar包的文件名,-m指定manifest.mf文件,-u添加文件到jar包中
其中MANIFEST.MF包含Multi-Release: true

小结

java9提供的multi-release jar的功能,可以在一个jar包打入多个jdk版本,同时在java9及以上的版本支持multi-release。它的好处就是比如从java8到java9的迁移,如果java8依赖的jar本身就是multi-release的,那么升级到java9就比较方便,不用再改maven依赖。不好的地方就是有过度设计的味道,一个jar包含多个版本的class,显得有些冗余。

doc

转载地址:http://mqzmx.baihongyu.com/

你可能感兴趣的文章
[MySQL] InnoDB三大特性之 - 自适应哈希索引
查看>>
Microsoft SQL Server 2008 基本安装说明
查看>>
ARM:移动GPU往PC GPU效能迈进
查看>>
uploadify API
查看>>
dp之多维背包hdu4501
查看>>
[置顶] 学习JDK源码:可进一步优化的代码
查看>>
Android中解决图像解码导致的OOM问题
查看>>
好的程序员习惯养成
查看>>
功能测试方法
查看>>
JAVA利用Zip4j解压缩【转】
查看>>
微博、博客和维基百科登图片不显示问题解决方法
查看>>
CSS hack
查看>>
svn 冲突
查看>>
也谈项目经理与敏捷开发
查看>>
js optimization and performance
查看>>
[UML]UML系列——类图Class
查看>>
SWFUpload 中文乱码问题
查看>>
[转]关于Json格式
查看>>
django 错误之 ImportError: No module named **
查看>>
Foglight 5.6.7 控制台jboss报404
查看>>