当前位置: 首页 > 面试题库 >

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

云曦之
2023-03-14
问题内容

我发现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将尝试内联出现的任何函数(基于运行时统计信息),这些函数经常被调用以使其值得使用。调用该函数是在一个位置还是在几十个位置上都没关系-
每个调用站点都单独进行分析。

请注意,该决定基于几个因素。该方法有多大?-如果有很多潜在的内联候选人,则仅内联最有利可图的候选人,以避免“代码膨胀”。但是呼叫的频率(乘以感知的呼叫费用)是最大的“得分”因素。

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

奇怪的是,可以阻止内联(以及许多其他东西)的另一件事是,无法从该方法返回。如果您输入了一个方法,然后在内部循环了1000万次而没有返回,则JITC将永远没有机会“交换”出已解释的方法并“交换”出已编译的方法。但是JITC通过使用仅编译一部分方法的技术来在某种程度上克服了这一问题,而其余部分则得到了解释。



 类似资料:
  • 问题内容: 例如,说我的头文件是: 和我的源文件 我可以将源文件拆分为 是否完全出于可读性考虑,而又不担心会对性能产生影响? 问题答案: 您应该标记函数,以便编译器知道它们在该翻译单元中是本地的。 没有编译器就不能假设(除非LTO / WPA)该函数仅被调用一次,因此不太可能内联它。 使用“ LLVM试用”页面进行演示。 就是说,首先要针对可读性的代码进行微优化(这种调整就是微优化),然后再执行性

  • 问题内容: 如果一个同步方法调用另一个同步方法,那么线程安全吗? 问题答案: 是的,将方法标记为时,您实际上是在这样做: 当线程调用从method1进入method2时,它将确保它持有对的锁定,该锁定已经存在,然后可以通过。 当线程直接进入method1或method2时,它将阻塞直到获得锁(),然后进入。 正如詹姆斯·布莱克(James Black)在评论中指出的那样,您必须了解方法主体内部的操

  • 例外情况。kt: 在科特林: 它在kotlin中工作,函数是内联的。 但是当在Java代码中使用时,它就是不能内联,仍然是一个正常的静态方法调用(从反编译的内容中可以看出)。 像这样的东西:

  • 本文向大家介绍是否可以从一个static方法内部发出对非static方法的调用?相关面试题,主要包含被问及是否可以从一个static方法内部发出对非static方法的调用?时的应答技巧和注意事项,需要的朋友参考一下 不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个stati

  • 我有一个函数定义为 (是映射到英特尔MIC体系结构上SIMD寄存器的本机数据类型) 由于这个函数相当短并且经常被调用,我希望它在每次调用时都内联。但是英特尔的编译器似乎不愿意内联这个函数,即使在我使用 - 和 选项之后也是如此。它报告说“Forceinline不被授予呼叫......”编译时。由于我必须使用一些编译器特定的功能,例如类型,英特尔编译器是我唯一的选择。 更多信息: 文件结构非常简单。

  • 我想你们大多数人都知道在Java语言中是一个保留的关键字,但实际上并没有被使用。你们可能也知道是一个Java虚拟机(JVM)操作码。我认为Java、Scala和静态编程语言的所有复杂的控制流结构都是在JVM级别上使用和、、等的某种组合来实现的。 查看JVM规范https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.