理解Java中的逃逸分析

名词解释:

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版本有用。

posted @ 2021-12-06 15:38  hucat  阅读(1029)  评论(2编辑  收藏  举报