12

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

4

2 回答 2

13

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

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

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

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

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

例如:

                           [all nominal types]
                     Object String Integer Number Comparable Iterable ...
[only       String   ✓      ✓                     ✓
 concrete   Integer  ✓             ✓       ✓      ✓
 types]     ...

当 JVM 必须对类进行垃圾收集时,维护此矩阵变得更加棘手,因此您通常使用类对象存储一行。


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

于 2013-10-05T15:09:09.877 回答
11

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

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

被编译成:

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
}

(这只是 的输出javap。)

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

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