简体   繁体   中英

What happens to Java object reference variable types after compilation?

I don't recall ever seeing any notion of reference variable types in Java bytecode. I know a bit about type erasure, but this term seems tightly linked to generics, whereas my question is about object reference variables in general. Do Java object reference variable types survive compilation ? Or do variable types merely serve the role of helping the compiler help the developer check that the code makes sense ? If reference variable types survive compilation, where do they appear in bytecode ?

EDIT: Allow me thank you here for all your valuable contributions. In order to narrow in a bit more on what I had in mind, I would like to add an example :

Object o = "foo";

In bytecode, will the variable o and its type (Object) be represented anywhere AND be read at runtime ?

Yes, bytecode is type-safe as well. First of all there is a byte code instruction called checkcast that is used every time you downcast:

Object obj = "abc";
String s = (String)obj;

is translated to:

aload_1       
checkcast     #3                  // class java/lang/String
astore_2   

Secondly invokevirtual and others expect an object of a given type. If you pass a wrong type, JVM will refuse loading such class. I don't think it's achievable in Java language, so I did a bit hacking. The following code:

Integer x = 1;
String s = "abc";
int len = s.length();

is translated to:

   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      

Notice instruction 8 that loads s local variable. Using hex editor I replaced aload_2 with aload_1 , thus trying to call String.length() on an Integer object ( x local variable):

$ 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

Just if you are curious, if you disable class verification, hell breaks loose:

$ 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)

Could've been worse.


Last but not least, there are plenty of opcodes dedicated to particular primitives (floats, doubles, ints, etc.)

All bytecode loaded by the JVM is statically type checked to make sure it's safe. Without type checking, malicious bytecode could just treat an int as a pointer and hack the VM.

However, just because the bytecode is typesafe doesn't mean that it has explicit typing. Instead, each value has an implicit type determined by type inference. (Starting with Java 7, it is also mandatory to include metadata specifying the types of everything at the start of each basic block, making the type inference task much easier).

Note that while everything is typechecked, the rules are more lax than in Java. For example, in bytecode, there is no such thing as a boolean, byte, char, or short local variable. They are all compiled to ints. So you can for instance have a boolean value that is not equal to true or false. Also, interfaces are not checked until you call a method on them, so an interface variable can actually hold any arbitrary object. Finally, the Hotspot VM allows you to freely intermix byte[] and boolean[]s.

The types of fields are encoded in the field descriptor .

The types of local variables may be encoded into the LocalVariableTable attribute (or the LocalVariableFieldTypeTable attribute for the generic type), and, in class files targeting Java 6, must be encoded in the StackMapTable attribute . For older class files, the JVM will verify type-correctness of bytecode with type inference .

So while you are correct that the types of fields and variables are not represented in bytecode, they are in the classfile (at least for class files targeting Java 6 or later).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM