⑩①. 栈上分配
- ①. JIT编译器在编译期间根据逃逸分析的结果,发现如果一个对象并没有逃逸出方法的话,就可能被优化成栈上分配
- ②.代码举例
/** * 栈上分配测试 * -Xmx256m -Xms256m -XX:-DoEscapeAnalysis -XX:+PrintGCDetails */ public class StackAllocation { public static void main(String[] args) { long start = System.currentTimeMillis(); for (int i = 0; i < 10000000; i++) { alloc(); } // 查看执行时间 long end = System.currentTimeMillis(); System.out.println("花费的时间为: " + (end - start) + " ms"); // 为了方便查看堆内存中对象个数,线程sleep try { Thread.sleep(1000000); } catch (InterruptedException e1) { e1.printStackTrace(); } } private static void alloc() { User user = new User(); //未发生逃逸 } static class User { } }
③. 未开启逃逸分析的情况
-Xmx256m -Xms256m -XX:-DoEscapeAnalysis -XX:+PrintGCDetails
日志打印发生了GC [GC (Allocation Failure) [PSYoungGen: 65536K->560K(76288K)] 65536K->568K(251392K), 0.0017179 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 66096K->464K(76288K)] 66104K->480K(251392K), 0.0017602 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 花费的时间为: 74 ms
④. 开启逃逸分析的情况
-Xmx256m -Xms256m -XX:+DoEscapeAnalysis -XX:+PrintGCDetails
日志打印:并没有发生 GC,耗时 3ms ,栈上分配是真的快啊 花费的时间为: 4 ms
⑩②. 同步替换 锁消除
- ①. 从JIT角度看相当于无视它了,这个锁对象没有被共享给其他线程
②. 例如下面的智障代码,根本起不到锁的作用
代码中对hellis这个对象加锁(每个线程都有一个hellis对象的锁),但是hellis对象的生命周期只在f( )方法中,并不会被其他线程所访问到,所以在JIT编译阶段就会被优化掉,优化成:
public void f() { Object hellis = new Object(); synchronized(hellis) { System.out.println(hellis); } } // JIT会将它变成这样 public void f() { Object hellis = new Object(); System.out.println(hellis); }
③. 注意:字节码文件中并没有进行优化,可以看到加锁和释放锁的操作依然存在,同步省略操作是在解释运行时发生的
⑩③. 分离对象或标量替换
①. 标量(scalar)是指一个无法再分解成更小的数据的数据。Java中的原始数据类型就是标量
②. 相对的,那些还可以分解的数据叫做聚合量(Aggregate),Java中的对象就是聚合量,因为他可以分解成其他聚合量和标量
③. 在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就
会把这个对象拆解成若干个其中包含的若干个成员变量来代替。这个过程就是标量替换
④. 举列子
public static void main(String args[]) { alloc(); } class Point { private int x; private int y; } private static void alloc() { Point point = new Point(1,2); System.out.println("point.x" + point.x + ";point.y" + point.y); } //以上代码,经过标量替换后,就会变成 private static void alloc() { int x = 1; int y = 2; System.out.println("point.x = " + x + "; point.y=" + y); }