私有方法内联

在Scala 不可变向量代码中有一条注释说:

原则上,大多数成员应该是私人的。 但是,必须谨慎选择访问权限,以防止方法内联

  1. 私人对内联决策的影响是什么?
  2. 这也适用于Java吗?

这通常不适用于Java。 访问检查仅在解决过程中执行一次。 当Java方法进行JIT编译时,符号引用已经过解析和validation。 实际上,内联不是在原始字节码上执行,而是在编译器特定的中间表示上执行。 因此,访问修饰符通常不具有性能副作用。

但是,我可以编写一个人工测试用例,其中private / public修饰符会显着影响性能:

 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 

这种效果通过合成方法access$000来解释, javac生成该方法以允许访问内部类的私有成员。 在上面的测试用例中,这个额外的访问器阻止了内联,因为HotSpot中默认的最大内联级别是9( -XX:MaxInlineLevel=9 )。 由于无法直接从外部类调用getPrivate() ,因此额外access$000()方法会进行第10级调用,因此不会内联。

我不是“编译器决策”的专家,但从逻辑上讲,我会说:

让我们想象这两个类(例如Java):

 class A { private B b; public void execute(){ b.execute(); } } class B { private int number; public void execute { println(number); } } 

如果编译器将B的execute内联到A的execute ,则会导致非法访问,因为B中的number是私有的:

 class A { private B b; public void execute(){ println(number); //OUPS! number is unreachable directly from A } } 

所以我会说,当你期望一些“内联”时,宁愿避免一些不兼容的变量的范围。

当然,我认为它在极少数情况下很有用(主要用于性能优化,我没想到其他情况)..也许你说的情况,否则会导致很多“糟糕的封装”……