包含私有调用的Java内联方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了包含私有调用的Java内联方法相关的知识,希望对你有一定的参考价值。

假设jvm将b.foo()方法标识为hot,它是否会尝试内联它?因为如果是这样,调用指令B.bar()将在A.main方法中内联,这是禁止的,因为bar是私有的。 jvm在这些情况下做了什么?

任何有更多细节的文档也会受到赞赏。谢谢

public class A {

    public static void main(String[] args)
    {
        B b = new B();
        for (int i=0; i<99999; i++)
            b.foo();
    }
}

class B {

    public void foo() {
        bar();
    }

    private void bar() { // do something. (is small method)
    }
}

编辑:我问,因为当我尝试自己做这个优化(在字节码中)我得到一个有意义的验证错误:

java.lang.VerifyError:Bad invokespecial instruction:当前类不能赋值给引用类

Aaditi:

public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=2, locals=5, args_size=1
     0: new           #13                 // class B
     3: dup
     4: invokespecial #14                 // Method B."<init>":()V
     7: astore_1
     8: iconst_0
     9: istore_2
    10: iload_2
    11: ldc           #15                 // int 99999
    13: if_icmpge     30
    16: aload_1
    17: astore        4
    19: aload         4
    21: invokespecial #18                 // Method B.bar:()V // VERIFY ERROR HERE
    24: iinc          2, 1
    27: goto          10
    30: return
  StackMapTable: number_of_entries = 2
    frame_type = 253 /* append */
      offset_delta = 10
      locals = [ class B, int ]
    frame_type = 19 /* same */
  LineNumberTable:
    line 5: 0
    line 6: 8
    line 7: 16
    line 14: 19
    line 15: 24
    line 6: 24
    line 8: 30
答案
  1. 在开始时,有源代码
  2. java编译器将其转换为字节码
  3. jvm读取字节码,验证其完整性并解释它。 “热点”(经常执行的代码块)的字节码即时编译到运行JVM的CPU的指令集中

在Java中,大多数优化在步骤3中推迟到JIT编译器,以便从程序执行期间收集的统计信息中受益。这包括内联。

访问修饰符(例如private)在验证期间,在解释字节码之前以及在JIT编译之前进行检查。由于已经检查了访问修饰符,因此JIT完全不知道它们的存在,并且内联私有方法不会造成任何困难。

顺便说一句,如果你想检查JIT的作用,你可以使用热点的-XX:+PrintAssembly将机器代码翻译成汇编代码供你检查。

另一答案

在Java中,优化通常在JVM级别完成。在运行时,JVM执行一些“复杂”分析以确定要内联的方法。它可以在内联方面具有攻击性,而Hotspot JVM实际上可以内联非最终方法。

java编译器几乎从不内联任何方法调用(JVM在运行时完成所有这些操作)。它们内联编译时间常数(例如最终的静态原始值)。但不是方法。

有关更多资源:

  1. Article: The Java HotSpot Performance Engine: Method Inlining Example
  2. Wiki: Inlining in OpenJDK,没有完全填充,但包含有用讨论的链接。

以上是关于包含私有调用的Java内联方法的主要内容,如果未能解决你的问题,请参考以下文章

如何管理在每个 git 版本中添加私有代码片段?

java反射访问私有方法的的问题

java--方法的定义与调用

java里一个私有的属性如何在其他类里面进行访问?

关于java中 子类 可否通过向上转型,调用父类私有成员方法

7. 第 7 章 类和对象简介