This generally does not apply to Java. The access checks are performed only once during the Resolution process. When Java method is JIT-compiled, the symbolic references are already resolved and verified. In fact, the inlining is performed not on the original bytecode, but on the compiler-specific intermediate representation. So, the access modifiers does not usually have performace side-effects.
However, I can write an artificial test case where a private
/public
modifier dramatically affects the performance:
public class Test {
static final Inner inner = new Inner();
static class Inner {
int x = 1;
int getX1() { return x; }
int getX2() { return getX1(); }
int getX3() { return getX2(); }
int getX4() { return getX3(); }
int getX5() { return getX4(); }
int getX6() { return getX5(); }
int getX7() { return getX6(); }
int getX8() { return getX7(); }
int getX9() { return getX8(); }
private int getPrivate() { return getX9(); }
public int getPublic() { return getX9(); }
}
@GenerateMicroBenchmark
public int inlinePrivate() {
return inner.getPrivate();
}
@GenerateMicroBenchmark
public int inlinePublic() {
return inner.getPublic();
}
}
Benchmark Mode Thr Cnt Sec Mean Mean error Units
b.Test.inlinePrivate thrpt 1 3 5 289480,928 2247,656 ops/msec
b.Test.inlinePublic thrpt 1 3 5 1157970,245 18473,139 ops/msec
This effect is explained by a synthetic method access$000
which javac
generates to allow access to a private member of the inner class. In the above test case this extra accessor prevents from inlining, because the default maximum level of inlining in HotSpot is 9 (-XX:MaxInlineLevel=9
). Since getPrivate()
cannot be called directly from the outer class, the extra access$000()
method makes 10th level of invocation and therefore is not inlined.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…