语法糖
public void forEach(ArrayList<Object> list, Consumer<Object> f) { for (Object obj : list) { f.accept(obj); } }
等价代码
public void forEach(ArrayList<Object> list, Consumer<Object> f) { Iterator<Object> iter = list.iterator(); while (iter.hasNext()) { Object obj = iter.next(); f.accept(obj); } }
迭代器:ArrayList$Itr
public class ArrayList ... { public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; ... public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } ... final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } }
假设即时编译器能够对上面这些方法都能 内联 :ArrayList$Itr(),hasNext(),next(),checkForComodification(),
可以得到类似的伪代码
public void forEach(ArrayList<Object> list, Consumer<Object> f) { Itr iter = new Itr; // new指令,分配内存空间,但未初始化,这里不是Java中的构造器调用 iter.cursor = 0; iter.lastRet = -1; iter.expectedModCount = list.modCount; while (iter.cursor < list.size) { if (list.modCount != iter.expectedModCount) throw new ConcurrentModificationException(); int i = iter.cursor; if (i >= list.size) throw new NoSuchElementException(); Object[] elementData = list.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); iter.cursor = i + 1; iter.lastRet = i; Object obj = elementData[i]; f.accept(obj); } }
伪代码中的ArrayList$Itr实例 既没有被存入任何字段之中 , 也没有作为任何方法调用的调用者或参数 ,可以断定该实例 不逃逸
即时编译器可以根据 逃逸分析的结果 进行如锁消除、栈上分配以及标量替换等优化
synchronized(new Object()){}
synchronized(escapedObject){}
,由于其他线程可能对该逃逸了的对象escapedObject进行加锁操作 public void forEach(ArrayList<Object> list, Consumer<Object> f) { // Itr iter = new Itr; // 经过标量替换后该分配无意义,可以被优化掉 int cursor = 0; // 标量替换 int lastRet = -1; // 标量替换 int expectedModCount = list.modCount; // 标量替换 while (cursor < list.size) { if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); int i = cursor; if (i >= list.size) throw new NoSuchElementException(); Object[] elementData = list.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; lastRet = i; Object obj = elementData[i]; f.accept(obj); } }
转载请注明出处:http://zhongmingmao.me/2019/01/05/jvm-advanced-escape/
访问原文「 JVM进阶 -- 浅谈逃逸分析 」获取最佳阅读体验并参与讨论