代码之家  ›  专栏  ›  技术社区  ›  user3213315

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

  •  7
  • user3213315  · 技术社区  · 10 年前

    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 回复  |  直到 7 年前
        1
  •  5
  •   Hot Licks    10 年前

    Java JITC将尝试内联任何看起来(基于运行时统计数据)足够频繁调用的函数。无论函数是在一个地方调用,还是在几十个地方调用——每个调用站点都是单独分析的。

    请注意,该决定基于几个因素。这个方法有多大是一个问题——如果有很多潜在的内联候选项,只有最有利可图的才会被内联,以避免“代码膨胀”。但电话频率(乘以电话的感知费用)是最大的“得分”因素。

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

    奇怪的是,另一个阻碍内联(以及许多其他东西)的因素是无法从方法返回。如果您有一个输入的方法,然后在内部循环1000万次而不返回,JITC永远不会有机会“交换”解释的方法和“交换”编译的方法。但JITC在一定程度上克服了这一点,只使用了编译方法的一部分的技术,其余部分则被解释。

        2
  •  4
  •   arshajii    10 年前

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

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


    从…起 http://www.oracle.com/technetwork/java/whitepaper-135217.html#method :

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

    内衬具有重要的优点。它大大降低了方法调用的动态频率,从而节省了执行这些方法调用所需的时间。但更重要的是,内联产生了更大的代码块供优化器处理。这就产生了一种情况,显著提高了传统编译器优化的效率,克服了提高Java编程语言性能的主要障碍。

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