1. Multi-Release jar概述
Java 9中提供了一个名为Multi-Release jar(mrjar)的新功能,它能够使得一个jar包中包含多个版本的class文件,使得一个jar包能够在不同版本的JRE上使用。这样做的好处在于,能够让程序在运行时自动根据当前的JRE版本选择最适合的class文件。同时,这也能够让开发者在使用新版本的Java API时,不必担心向下兼容性问题。
2. Multi-Release jar的工作原理
2.1 jar文件结构
一个普通的jar包的目录结构如下:
jarFile.jar
└── com
└── example
└── MyClass.class
其中MyClass.class是一个针对JRE版本A编译的版本,该版本的class文件不能在低于JRE版本A的环境中使用。如果我们在低于JRE版本A的环境中运行jarFile.jar,则会出现异常。
而在Multi-Release jar中,我们可以在jar包中提供多个版本的class文件,如下:
jarFile.jar
├── com
│ └── example
│ ├── MyClass.class
│ └── MyClass.class // 针对JRE版本B的新版本
└── META-INF
└── versions
├── 9
│ └── com
│ └── example
│ ├── MyClass.class // 针对JRE版本9的新版本
│ └── MyNewClass.class // 针对JRE版本9的全新class文件
└── 10
└── com
└── example
└── MyClass.class // 针对JRE版本10的新版本
上述目录结构中,我们为各个版本的class文件制定了特定的目录。其中,版本9和版本10的目录中存放的是对应的JRE版本所需要的class文件,而根目录和通用版本的目录中,我们存放了针对低版本JRE的class文件。
2.2 MANIFEST.MF文件
除了上述的目录结构外,Multi-Release jar还需要在MANIFEST.MF文件中声明自己是一个Multi-Release jar,并指定默认版本的目录,如下所示:
Manifest-Version: 1.0
Multi-Release: true
Main-Class: com.example.Main
2.3 运行时选择版本
当我们在运行Multi-Release jar时,Java虚拟机会根据当前运行环境的版本自动选择相应的class文件。如果当前运行的是针对版本B的JRE,则会选择通用版本的class文件。如果当前运行的是针对JRE版本9的JRE,则会选择versions/9目录下的class文件。
3. 使用Multi-Release jar
3.1 创建Multi-Release jar包
创建Multi-Release jar包比普通的jar包要复杂一些。需要手动组织目录结构和MANIFEST.MF文件。我们可以使用以下命令来创建一个Multi-Release jar包:
jar -c -v -f demo.mrjar -m META-INF/MANIFEST.MF -C classes .
jar -u -v --release 9 -f demo.mrjar -C classes/java9 .
上述命令中,第一条命令会创建一个普通的jar包,其中包含java8版本的class文件。第二条命令会向jar包中添加针对Java 9的class文件,这些文件会被存放在META-INF/versions/9目录下。这里的--release 9表示我们添加的class文件是针对Java 9版本的。
3.2 使用Multi-Release jar包
使用Multi-Release jar包与使用普通的jar包类似,只是需要在启动时指定-jar参数,并保证使用的JRE版本高于或等于该jar包中针对的最高版本。例如:
java -jar demo.mrjar
如果当前环境的JRE版本低于该jar包中指定的最高版本,则会报错。
4. 总结
Java 9中提供的Multi-Release jar是一个非常实用的功能,它能够让一个jar包同时适用于多个JRE版本,并且能够自动切换使用哪个版本的class文件。这对于使用新版本Java API的开发者来说,能够带来非常大的便利。不过,使用Multi-Release jar也需要注意一些问题,例如确保目录结构正确,以及保证使用的JRE版本高于或等于该jar包中针对的最高版本。