脚本宝典收集整理的这篇文章主要介绍了

Java中的逃逸分析

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。

1.引言

Java 程序运行时,JVM 会将 .class 字节码转换成机器能够识别的指令,指令转换过程会产生耗时,延缓程序的运行速度,为了解决这种问题出现了「JIT(即时编译)」技术。JIT 主要有两个功能:

  • 缓存「Hot Spot Code(热点代码:频繁运行的方法或代码块)」对应的机器指令,方便下次调用。
  • 代码编译优化。

而在 JIT 的代码优化过程中,最重要的就是「逃逸分析(Escape Analysis)」。

2. 逃逸分析

逃逸分析就是 分析Java对象的动态作用域。当一个对象被定义之后,可能会被外部对象引用,称之为「方法逃逸」;也有可能被其他线程所引用,称之为「线程逃逸」。

public class EscapeObject {     public static String createStr() {         String sb = "hello world!";         return sb;     } }

例如上面这段代码将创建的字符串对象 sb 返回,这样可以被其他方法或线程引用。

public class EscapeObject {     public static String createStr() {         StringBuffer sb = new StringBuffer("hello world!");         return sb.toString();     } }

如果这样实现的话,sb 对象就没有「逃逸」。

利用逃逸分析,编译器可以对代码做如下优化:

  1. 同步省略
  2. 标量替换
  3. 栈上分配

2.1 同步省略

在 JIT 编译过程中,如果发现一个对象不会被多线程访问,那么针对这个对象的同步措施就可以省略掉,即「锁销除」。例如 Vector 和 StringBuffer 这样的类,它们中的很多方法都是有锁的,当某个对象确定是线程安全的情况下,JIT编译器会在编译这段代码时进行锁销除来提升效率。

2.2 标量替换

「标量(Scalar)」是指无法再分解成更小粒度的数据,例如 Java 中的原始数据类型(intlong等),相对如果一个数据可以继续分解,则称之为「聚合量(Aggregate)」,例如 Java对象。在 JIT 编译过程中,经过逃逸分析确定一个对象不会被其他线程或者方法访问,那么会将对象的创建替换成为多个成员变量的创建,称之为「标量替换」。

public class EscapeObject {      private static void getUser() {         User user = new User("张三", 18);         System.out.println("user name is " + user.name + ", age is " + user.age);     }      public static void main(String[] args) {         getUser();     } }  class User {     String name;     int age;      public User(String name, int age) {         this.name = name;         this.age = age;     } }

上面这段代码中,对象 user 只会在getUser()方法中被调用,那么 JIT动态编译时,不会创建对象 user,而之创建它的两个成员变量 name 和 age,类似:

private static void getUser() {     String name = "张三";     int age = 18;      System.out.println("user name is " + user.name + ", age is " + user.age);  }  public static void main(String[] args) {     getUser(); }

标量替换减少了创建对象需要的堆内存,同时也不用进行 GC。

2.3 栈上分配

「栈上分配」是指对象和数据不是创建在堆上,而是创建在栈上,随着方法的结束自动销毁。但实际上,JVM 例如常用的「HotSpot」虚拟机并没有实现栈上分配,实际是用「标量替换」代替实现的。

在 JAVA 中,对象只分配在堆中:

The heap is the runtime data area from which memory for all class instances and arrays is allocated  堆是所有的对象实例以及数组分配内存的运行时数据区域。

2.4 如何开启逃逸分析

可以通过设置 JVM 参数来开启或关闭逃逸分析

  • -XX:+DoEscapeAnalysis :开启逃逸分析(从JDK1.7开始默认开启)
  • -XX:-DoEscapeAnalysis :关闭逃逸分析

3. 参考资料

总结

以上是脚本宝典为你收集整理的

Java中的逃逸分析

全部内容,希望文章能够帮你解决

Java中的逃逸分析

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过