名词解释:
JIT(Just-In-Time Compilation):实时编译。
有关JIT的概念,可以看我的另一篇文章:《JIT实时编译特性》
在JVM的实现中,为了提高JVM的性能和节省内存空间,JVM提供了一种叫做 “逃逸分析” 的特性,而且对于“逃逸分析” 这种特性,也是近年来大厂面试常问的知识点。今天,我们就一起来聊聊什么是逃逸分析。
逃逸分析的官方定义:一种确定指针动态范围的静态分析,它可以分析在程序的哪些地方可以访问到指针。
很难理解对不对,简单点说就是:一种分析手段,用于确定对象的作用范围。
分析的结果:不逃逸、方法逃逸、线程逃逸。
- 不逃逸、方法逃逸:对象放到栈中(为了节约栈空间,还会做标量替换等操作,可参考《JIT实时编译特性》)。放到栈中的对象会随着方法结束而销毁,把不必放到堆中的对象放到了栈中。减轻了垃圾回收的压力。
- 线程逃逸:对象放到堆中。
下面举例说明:
//不逃逸 public static void main(String[] args) { String sb = createStringBuffer("a", "b"); sb.length(); } public static String createStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb.toString(); } //方法逃逸 public static void main(String[] args) { StringBuffer sb = createStringBuffer("a", "b"); sb.reverse(); } public static StringBuffer createStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb; } //线程逃逸 public static void main(String[] args) { StringBuffer sb = createStringBuffer("a", "b"); new Thread(() -> { sb.reverse(); }).start(); } public static StringBuffer createStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb; }
在Java代码运行时,通过JVM参数可指定是否开启逃逸分析,
-XX:+DoEscapeAnalysis : 表示开启逃逸分析
-XX:-DoEscapeAnalysis : 表示关闭逃逸分析 从jdk 1.7开始已经默认开始逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis
那么有关Java逃逸分析的介绍就到这里了,有问题欢迎在评论区留言讨论,我看到后也会回复的。
Tips:如果想看逃逸分析日志,可以添加java参数:-XX:+PrintEscapeAnalysis来打印。但是这个参数只有在debug版本的jdk版本有用。