如何在JVM中实现'instanceof'?

arn*_*hen 5 java jvm instanceof

它是否使用反射,如果是,那么幕后发生了什么?

Mik*_*uel 12

Jon对于运算符如何映射到字节码是正确的.就实现而言,大多数JVM将内存中的对象表示为已加载的具体类的标记联合:

标记联合,也称为变体,变体记录,区分联合,不相交联合或和类型,是用于保存可以采用几种不同但固定类型的值的数据结构.

因此,当具体类型是类类型的实例时,x instanceof MyClassType可以通过查看具有位设置的稀疏布尔矩阵来回答.

x instanceof InterfaceType 有点棘手,但类似的方法也可以帮助解决这个问题.

JVM可以在内存中保留一个大的稀疏矩阵,每个标称类型(类或接口类型)有一行,每个类类型有一列.

例如:

                           [all nominal types]
                     Object String Integer Number Comparable Iterable ...
[only       String   ?      ?                     ?
 concrete   Integer  ?             ?       ?      ?
 types]     ...
Run Code Online (Sandbox Code Playgroud)

当JVM必须垃圾收集类时,维护此矩阵变得更加棘手,因此通常存储一个包含类对象的行.


代理类是一个有趣的角落案例,但我最好的猜测是代理类定义涉及在运行时生成一些字节代码,然后通过大多数JVM中的普通类加载系统.


Jon*_*eet 9

它是JVM指令集的一部分,基本上 - 有一个特定的instanceof指令.例如,像这样的方法:

public static void checkString(Object x) {
    if (x instanceof String) {
        System.out.println("Foo");
    }
}
Run Code Online (Sandbox Code Playgroud)

编译成:

public static void checkString(java.lang.Object);
  Code:
     0: aload_0
     1: instanceof    #2                  // class java/lang/String
     4: ifeq          15
     7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
    10: ldc           #4                  // String Foo
    12: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    15: return
}
Run Code Online (Sandbox Code Playgroud)

(这只是输出javap.)

JVM规范具有什么样的指令必须做的详细信息.有关说明的详细信息,请参见第6.5节.它的实现方式取决于VM的实现 - 但是一个示例实现可能是:

  • 检查第一个操作数是否为null(false如果是则返回)
  • 查找第一个操作数引用的对象的执行时类型.
  • 向上导航类型层次结构(包括已实现的接口),直到您可以证明实际类型与第二个操作数兼容或不兼容.