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

时间:2014-07-24 00:03:13

标签: java performance code-organization

I found out that the C++ compiler does so但我想知道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
}

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

如果这是一个不好的问题,请告诉我,我会删除它。

2 个答案:

答案 0 :(得分:4)

Java JITC将尝试内联任何出现的函数(基于运行时统计信息),以便经常调用它们。是否仅在一个地方或几十个地方调用该功能并不重要 - 每个呼叫站点都是单独分析的。

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

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

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

答案 1 :(得分:3)

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

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


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

  

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

     

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

     

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