锁消除
我们知道线程同步锁是非常牺牲性能的,当编译器确定当前对象只有当前线程使用,那么就会移除该对象的同步锁。
例如,StringBuffer 和 Vector 都是用 synchronized 修饰线程安全的,但大部分情况下,它们都只是在当前线程中用到,这样编译器就会优化移除掉这些锁操作。
锁消除的 JVM 参数如下:
开启锁消除:-XX:+EliminateLocks
关闭锁消除:-XX:-EliminateLocks
锁消除在 JDK8 中都是默认开启的,并且锁消除都要建立在逃逸分析的基础上。
标量替换
首先要明白标量和聚合量,基础类型和对象的引用可以理解为标量,它们不能被进一步分解。而能被进一步分解的量就是聚合量,比如:对象。
对象是聚合量,它又可以被进一步分解成标量,将其成员变量分解为分散的变量,这就叫做标量替换。
这样,如果一个对象没有发生逃逸,那压根就不用创建它,只会在栈或者寄存器上创建它用到的成员标量,节省了内存空间,也提升了应用程序性能。
标量替换的 JVM 参数如下:
开启标量替换:-XX:+EliminateAllocations
关闭标量替换:-XX:-EliminateAllocations
显示标量替换详情:-XX:+PrintEliminateAllocations
标量替换同样在 JDK8 中都是默认开启的,并且都要建立在逃逸分析的基础上。
栈上分配
当对象没有发生逃逸时,该对象就可以通过标量替换分解成成员标量分配在栈内存中,和方法的生命周期一致,随着栈帧出栈时销毁,减少了 GC 压力,提高了应用程序性能。
java8最大的特性就是引入Lambda表达式,即函数式编程,可以将行为进行传递。总结就是:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。
集合有两种方式生成流:
stream() − 为集合创建串行流
parallelStream() - 为集合创建并行流
中间操作主要有以下方法(此类型方法返回的都是Stream):map (mapToInt, flatMap 等)、 filter(过滤)、 distinct(去重)、 sorted、 peek、 limit(返回指定流个数)、 skip(跳过流中的元素)、 parallel、 sequential、 unordered
终止操作主要有以下方法:forEach、 forEachOrdered、 toArray、 reduce(将流中的元素组合起来)、 collect、 min、 max、 count(流中元素的个数)、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
@Data
public class Dish {
private String name;
private boolean vegetarian;
private int calories;
}
private List afterJava8(List dishList) {
return dishList.stream()
.filter(d -> d.getCalories() < 400) //筛选出卡路里小于400的菜肴
.sorted(comparing(Dish::getCalories)) //根据卡路里进行排序
.map(Dish::getName) //提取菜肴名称
.collect(Collectors.toList()); //转换为List
}
Optional 类主要解决的问题是空指针异常(NullPointerException),本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。Optional 是 Java 实现函数式编程的强劲一步
Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。
1: or() 方法与 orElse() 和 orElseGet() 类似,它们都在对象为空的时候提供了替代情况。or() 的返回值是由 Supplier 参数产生的另一个 Optional 对象。
2: ifPresentOrElse() 方法需要两个参数:一个 Consumer 和一个 Runnable。如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。
3: stream() 方法,它通过把实例转换为 Stream 对象,让你从广大的 Stream API 中受益。如果没有值,它会得到空的 Stream;有值的情况下,Stream 则会包含单一值。
public static void main(String[] args) throws IOException {
Path dir = Paths.get("d:/");
Path path1 = dir.resolve("javastack1.txt");
Path path2 = dir.resolve("javastack2.txt");
long result = Files.mismatch(path1, path2);
System.out.println(result);
}
Files.mismatch方法源码如下:
public static long mismatch(Path path, Path path2) throws IOException {
if (isSameFile(path, path2)) {
return -1;
}
byte[] buffer1 = new byte[BUFFER_SIZE];
byte[] buffer2 = new byte[BUFFER_SIZE];
try (InputStream in1 = Files.newInputStream(path);
InputStream in2 = Files.newInputStream(path2);) {
long totalRead = 0;
while (true) {
int nRead1 = in1.readNBytes(buffer1, 0, BUFFER_SIZE);
int nRead2 = in2.readNBytes(buffer2, 0, BUFFER_SIZE);
int i = Arrays.mismatch(buffer1, 0, nRead1, buffer2, 0, nRead2);
if (i > -1) {
return totalRead + i;
}
if (nRead1 < BUFFER_SIZE) {
// we've reached the end of the files, but found no mismatch
return -1;
}
totalRead += nRead1;
}
}
}
解释:返回-1:同一文件,或者两个文件内容一样;其他数字:文件内容对比差异的位置,从0开始
private static void testSwitch3(Status status) {
var result = switch (status) {
case OPEN -> {
break 1;
}
case PROCESS, PENDING -> {
break 2;
}
case CLOSE -> {
break 3;
}
default -> {
break 5;
}
};
System.out.println("result is " + result);
}
private static void testSwitch2(Status status) {
var result = switch (status) {
case OPEN -> 1;
case PROCESS, PENDING -> 2;
case CLOSE -> 3;
default -> throw new RuntimeException("状态不正确");
};
System.out.println("result is " + result);
}
JDK13之前
String html = "\n" +
" \n" +
" Hello, world
\n" +
" \n" +
"\n";
JDK13优化的:
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
2:SQL变化
JDK13之前
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
"WHERE `CITY` = 'INDIANAPOLIS'\n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;\n";
JDK13
String query = """
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";
3:解释
文本块
"""
line 1
line 2
line 3
"""
相当于字符串文字:
"line 1\nline 2\nline 3\n"
摘要:增强ZGC以将未使用的堆内存返回给操作系统。
动机:ZGC目前没有取消提交并将内存返回给操作系统,即使该内存长时间未使用。对于所有类型的应用程序和环境,此行为并非最佳, 尤其是那些需要关注内存占用的应用程序和环境 例如:通过使用支付资源的容器环境。应用程序可能长时间处于空闲状态并与许多其 他应用程序共享或竞争资源的环境。应用程序在执行期间可能具有非常不同的堆空间要求。
例如:启动期间所需的堆可能大于稳态执行期间稍后所需的堆。HotSpot中的其他垃圾收集器,如G1和Shenandoah,今天提供 了这种功能,某些类别的用户发现它非常有用。将此功能添加到ZGC将受到同一组用户的欢迎。
摘要:使用更简单,更现代的实现替换java.net.Socket和java.net.ServerSocketAPI 使用的底层实现,易于维护和调试。新的实现很容易适应用户模式线程,也就是光纤,目前正在Project Loom中进行探索。
动机:在java.net.Socket和java.net.ServerSocketAPI,以及它们的底层实现,可以追溯到JDK 1.0。实现是遗留Java和C代码的混合,维护和调试很痛苦。该实现使用线程堆栈作为I/O缓冲区,这种方法需要多次增加默认线程堆栈大小。
核心库/ java.nio中添加了FileSystems.newFileSystem(Path,Map )方法
添加了三种新方法java.nio.file.FileSystems,以便更轻松地使用将文件内容视为文件系统的文件系统提供程序。
1、newFileSystem(Path)
2、newFileSystem(Path, Map)
3、newFileSystem(Path, Map, ClassLoader)
添加为newFileSystem(Path, Map<String, ?>) 已使用现有newFileSystem(Path, ClassLoader)并指定类加载器 的代码创建源(但不是二进制)兼容性问题。例如,由于引用newFileSystem不明确,因此无法编译以下内容:
FileSystem fs = FileSystems.newFileSystem(path, null);
为了避免模糊引用,需要修改此代码以将第二个参数强制转换为java.lang.ClassLoader。
1 该com.sun.security.crl.readtimeout系统属性设置为CRL检索的最大读取超时,单位为秒。如果尚未设置该属性,或者其值为负,则将其设置为默认值15秒。值0表示无限超时。
2 新的keytool -showinfo -tls用于显示TLS配置信息的命令keytool -showinfo -tls添加了一个显示TLS配置信 息的新命令。
3 SunMSCAPI提供程序现在支持以下一代加密(CNG)格式读取私钥。这意味着CNG格式的RSA和EC密钥可从Windows密钥 库加载,例如“Windows-MY”。与EC(签名算法SHA1withECDSA,SHA256withECDSA等等)也支持。