是的,字节码也是类型安全的。首先,每次向下转换时都会使用一个字节码指令:checkcast
Object obj = "abc";
String s = (String)obj;
被翻译成:
aload_1
checkcast #3 // class java/lang/String
astore_2
其次invokevirtual
,其他人期望给定类型的对象。如果您传递了错误的类型,JVM 将拒绝加载此类。我不认为用 Java 语言可以实现,所以我做了一些黑客攻击。以下代码:
Integer x = 1;
String s = "abc";
int len = s.length();
被翻译成:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: ldc #3 // String abc
7: astore_2
8: aload_2
9: invokevirtual #4 // Method java/lang/String.length:()I
12: istore_3
8
注意加载s
局部变量的指令。使用十六进制编辑器替换aload_2
为aload_1
,从而尝试调用String.length()
对象Integer
(x
局部变量):
$ java Test
Exception in thread "main" java.lang.VerifyError:
Bad type on operand stack in method Test.main([Ljava/lang/String;)V at offset 9
只是如果你好奇,如果你禁用类验证,地狱就会崩溃:
$ java -Xverify:none Test
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.length(String.java:623)
at Test.main(Test.java:6)
本来可以更糟的。
最后但同样重要的是,有大量专用于特定原语(浮点数、双精度数、整数等)的操作码。