Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 843
Student Avatar asked Jan 31 '26 19:01

Student


1 Answers

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

like image 174
Tomasz Nurkiewicz Avatar answered Feb 03 '26 08:02

Tomasz Nurkiewicz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!