测试的POM文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc.jdk12</groupId>
<artifactId>jdk12</artifactId>
<version>1.0.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
<!-- JMH -->
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.11.2</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.11.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<!--使用 enable-preview和release12参数编译代码-->
<configuration>
<release>12</release>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-shade-plugin</artifactId>-->
<!-- <version>3.1.0</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <phase>package</phase>-->
<!-- <goals>-->
<!-- <goal>shade</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <finalName>microbenchmarks</finalName>-->
<!-- <transformers>-->
<!-- <transformer-->
<!-- implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">-->
<!-- <mainClass>com.imooc.jdk.Main</mainClass>-->
<!-- </transformer>-->
<!-- </transformers>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
</plugins>
</build>
</project>
1、JEP 230: Microbenchmark Suite
测试:
@Fork(2) //进行fork的次数,生成的进程次数
@Threads(8) //指定每个进程中的测试线程
@BenchmarkMode(Mode.Throughput) //基准测试的类型,Throughput表示吞吐量,AverageTime平均时间,SampleTime随机取样,
// SingleShotTime表示单次运行,All表示执行所有的模式
@Warmup(iterations = 5) //程序启动慢,进行预热,iterations表示预热的轮数
@Measurement(iterations = 10, time = 5) //度量,iterations表示进行轮次,time表示进行的时长
@OutputTimeUnit(TimeUnit.NANOSECONDS) //基准测试输出的时间类型
public class BenchmarkTest {
@Benchmark //表示当前方法是需要进行基本测试的对象
public void testStringAdd() {
String a = "";
for (int i = 0; i < 10; ++i) {
a += i;
}
// System.out.println(a);
}
@Benchmark
public void testStringBuilderAdd() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; ++i) {
sb.append(i);
}
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder().include(BenchmarkTest.class.getSimpleName())
.output("benchmark.log") //打印测试文件输出到指定文件里
.build();
new Runner(options).run();
}
}
结果:
2、JEP 325: Switch Expressions (Preview)
对switch进行了增强,除了使用statement还可以使用expression,比如原来的写法如下:
测试:
public class SwitchExample {
public static void main(String[] args) {
switch (Calendar.MONDAY) {
case Calendar.MONDAY -> System.out.println(1);
case Calendar.TUESDAY -> System.out.println(2);
default -> System.out.println(0);
}
int result = switch (Calendar.MONDAY) {
case Calendar.MONDAY -> 1;
case Calendar.TUESDAY -> 2;
default -> 0;
};
System.out.println(result);
}
}
编译:
单文件运行:
3、JEP 341: Default CDS Archives
java10的新特性JEP 310: Application Class-Data Sharing扩展了JDK5引入的Class-Data Sharing,支持application的Class-Data Sharing;Class-Data Sharing可以用于多个JVM共享class,提升启动速度,最早只支持system classes及serial GC,JDK9对其进行扩展以支持application classes及其他GC算法,并在JDK10中开源出来(以前是commercial feature);JDK11将-Xshare:off改为默认-Xshare:auto,以更加方便使用CDS特性;JDK12的这个特性即在64-bit平台上编译jdk的时候就默认在${JAVA_HOME}/lib/server目录下生成一份名为classes.jsa的默认archive文件(大概有18M)方便大家使用
4、G1垃圾器功能增强
JEP 344: Abortable Mixed Collections for G1
G1在garbage collection的时候,一旦确定了collection set(CSet)开始垃圾收集这个过程是without stopping的,当collection set过大的时候,此时的STW时间会过长超出目标pause time,这种情况在mixed collections时候比较明显。这个特性启动了一个机制,当选择了一个比较大的collection set,允许将其分为mandatory及optional两部分(当完成mandatory的部分,如果还有剩余时间则会去处理optional部分)来将mixed collections从without stopping变为abortable,以更好满足指定pause time的目标
JEP 346: Promptly Return Unused Committed Memory from G1
G1目前只有在full GC或者concurrent cycle的时候才会归还内存,由于这两个场景都是G1极力避免的,因此在大多数场景下可能不会及时会还committed Java heap memory给操作系统。JDK12的这个特性新增了两个参数分别是G1PeriodicGCInterval及G1PeriodicGCSystemLoadThreshold,设置为0的话,表示禁用。当上一次garbage collection pause过去G1PeriodicGCInterval(milliseconds)时间之后,如果getloadavg()(one-minute)低于G1PeriodicGCSystemLoadThreshold指定的阈值,则触发full GC或者concurrent GC(如果开启G1PeriodicGCInvokesConcurrent),GC之后Java heap size会被重写调整,然后多余的内存将会归还给操作系统
5、jdk12其他新特性
JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)
Shenandoah GC是一个面向low-pause-time的垃圾收集器,它最初由Red Hat实现,支持aarch64及amd64 architecture;ZGC也是面向low-pause-time的垃圾收集器,不过ZGC是基于colored pointers来实现,而Shenandoah GC是基于brooks pointers来实现;如果要使用Shenandoah GC需要编译时–with-jvm-features选项带有shenandoahgc,然后启动时使用-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
JEP 334: JVM Constants API
新增了JVM Constants API,具体来说就是java.base模块新增了java.lang.constant包,引入了ConstantDesc接口(ClassDesc、MethodTypeDesc、MethodHandleDesc这几个接口直接继承了ConstantDesc接口)以及Constable接口;ConstantDesc接口定义了resolveConstantDesc方法,Constable接口定义了describeConstable方法;String、Integer、Long、Float、Double均实现了这两个接口,而EnumDesc实现了ConstantDesc接口
JEP 340: One AArch64 Port, Not Two
64-bit Arm platform (arm64),也可以称之为aarch64;之前JDK有两个关于aarch64的实现,分别是src/hotspot/cpu/arm以及open/src/hotspot/cpu/aarch64,它们的实现重复了,为了集中精力更好地实现aarch64,该特性在源码中删除了open/src/hotspot/cpu/arm中关于64-bit的实现,保留其中32-bit的实现,于是open/src/hotspot/cpu/aarch64部分就成了64-bit ARM architecture的默认实现