语法糖
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进阶 -- 浅谈逃逸分析 」获取最佳阅读体验并参与讨论