Java逃逸分析
1. 什么是Java逃逸分析
我们知道对象一般是在堆上生成的,但这并不是绝对的。特例就是今天要说的逃逸分析。
JVM 在分析代码以后,发现一个对象在声明之后,只有在它当前声明的这个函数中调用,那么它就会将这个对象在栈上申请空间。而不是在堆上。这就是JDK6出的逃逸分析。因为在栈上创建的对象,在函数执行完毕以后,会将这个对象清理。这样就大大减轻了GC的压力。
2. 举一个例子
写一段代码
现在在代码里面声明了一个Integer 对象。注意这个对象要大于127。或者要小于-128。why?
Boolean、Byte的所有对象,都是预先创建好的(类加载的时候)Character、Short、Integer、Long是-128~127的对象是预先创建好的(Character没有负数)
如果new Integer(1)则是从创建好的缓存中,直接拿出,因而是同一个。
为了节省内存,这些数字使用概率很高,早就创建好,之后都用同一个,是提高效率的做法。
package org.example;
public class Main2 {
public static void main(String[] args) {
while (true) {
Integer integer = new Integer(1111);
}
}
}
设置JVM内存
编辑运行的模式,设置堆的最大为10M,最小也为10M,也就是堆的大小就是10M,并且设置打印GC的过程。设置堆的大小为10M的原因是JVM 可以尽快的进入GC。
设置JVM堆大小的命令如下:
-Xmx10m -Xms10m -XX:+PrintGC
关闭逃逸分析,观察现象
因为JDK6以后,默认开了逃逸分析。可以通过 -XX:-DoEscapeAnalysis, 可以关闭逃逸分析。
关闭逃逸分析,运行程序,我们可以看到程序在疯狂的进行GC。
开启逃逸分析,观察现象
开启逃逸分析,运行程序,只看到程序只进行了2次GC。这就是逃逸分析带来的好处。
3. 小结
逃逸分析是分析了对象只在当前函数范围内使用,因而改为在栈上申请空间。而栈是函数运行完毕以后,就会立即清理的。所以不需要等到GC了,大大缓解了GC的压力。当然如果不是只在当前函数范围内用到的对象不行。