现代Java编译器/ JVM内联函数/方法是否完全从一个地方调用?

我发现C ++编译器这样做但我想知道Java编译器是否也这样做,因为在那个答案中他们说添加静态会这样做但是静态在java和C ++中是不同的。 在我的情况下,性能很重要,因为我使用的函数在游戏循环中每帧只调用一次,而在其他地方调用,以使其更具可读性
在我的代码中,我设置类似于此,除了更多的调用

while(running) { update(); sync(); } 

然后update(),render()会调用更多调用其他方法的方法

 private final void update() { switch(gameState) { case 0: updateMainMenu(); renderMainMenu(); break; case 1: updateInGame(); renderInGame(); break; //and so on } } private final void updateInGame() { updatePlayerData(); updateDayCycle(); //and so on } private final void updatePlayerData() { updateLocation(); updateHealth(); //and so on } 

那么编译器是否会内联这些函数,因为它们只在同一位置每帧使用一次?

如果这是一个糟糕的问题,请告诉我,我将删除它。

Java JITC将尝试内联出现的任何函数(基于运行时统计信息),以便经常调用它们。 无论是在一个地方还是几十个地方调用该function都无关紧要 – 每个呼叫站点都是单独分析的。

请注意,该决定基于几个因素。 这个方法有多大 – 如果有很多潜在的内联候选人,那么只有最有利可图的人才会被内联,以避免“代码臃肿”。 但是呼叫的频率(乘以感知的呼叫费用)是最大的“得分”因素。

阻止内联的一件事是明显的多态调用。 如果一个调用可能是多态的,那么必须通过代码来“保护”它,如果到达的类不是预期的类,它将执行原始调用。 如果统计数据certificate调用通常是多态的(并且包括所有多态变体都不值得)那么内联可能没有足够的利润。 静态或最终方法是最有吸引力的,因为它不需要保护。

另一件可以阻止内联(以及许多其他内容)的事情,奇怪的是,无法从方法返回。 如果你有一个输入的方法,然后在内部循环1000万次而不返回,JITC永远不会有机会“换出”解释的方法并“交换”已编译的方法。 但JITC通过使用仅编译方法的一部分的技术在一定程度上克服了这一点,其余部分被解释。

为了将来参考,您可以使用javap -c MyClass查看.class文件的字节码,以查看编译代码的外观。

回答你的问题:Java 编译器没有内联方法。 另一方面,JVM会分析您的代码,并在必要时在运行时内联。 基本上,你不应该担心它 – 把它留给JVM,如果它发现它有益,它将内联。 在这些事情上,JVM通常比你更聪明。


来自http://www.oracle.com/technetwork/java/whitepaper-135217.html#method :

方法内联
Java编程语言中虚拟方法调用的频率是一个重要的优化瓶颈。 一旦Java HotSpot自适应优化器在执行期间收集有关程序热点的信息,它不仅将热点编译为本机代码,而且还对该代码执行大量方法内联。

内联具有重要的好处。 它大大降低了方法调用的动态频率,从而节省了执行这些方法调用所需的时间。 但更重要的是,内联会为优化程序生成更大的代码块。 这创造了一种能够显着提高传统编译器优化效率的情况,克服了增加Java编程语言性能的主要障碍。

内联与其他代码优化具有协同作用,因为它使它们更有效。 随着Java HotSpot编译器的成熟,对大型内联代码块进行操作的能力将为未来的一系列更高级的优化打开大门。