Often, writing code requires to test assumptions. The easiest way is often to do some research on the net. But when the first few queries do not return a useful result, it is time to test the assumption by ourselves.
In my case, I was wondering whether explicitly casting a variable to its static type introduces a cast in the compiled bytecode1.
For instance, in the program below the cast from int
to int
is useless and could be removed during compilation.
|
|
Of course, if written by hand, the best design decision is to simply remove the cast and to continue coding. But, in my case, the Java code is generated by a compiler, which left me two choices. Either add some logic to my compiler and remove useless casts during code generation. Or, left them in place and let the Java compiler do the heavy lifting.
I’d rather avoid complexifying my compiler for now, and I’d be happier with a few useless casts in the generated Java source code, but only if they are finally removed from the Java bytecode.
This is why I want to validate the following question:
Does javac cleanup useless type cast?
I based my experiment on the sample below, where a callMe(B b)
method is called three times on different configurations.
The first call is our baseline, what one would write manually. The second call introduce a useless cast since b
is already statically of type B
.
Finally, the third does a down-cast of a
to type B
.
Only the later is expected to produce a cast operation in the compiled bytecode.
|
|
Compiling the java classes is straightforward and lead to the compilation of three classes: WithCasts
and the two inner classes WithCasts$A
and WithCasts$B
.
|
|
Now, time to inspect the bytecode using javap
2.
I won’t go into the details of how to read bytecode, but I found it useful to get enough knowledge to be minimally knowledgeable on the topic3. The bytecode below is annotated in order to ease its reading.
|
|
We now have enough information to validate our hypothesis, callMe((B) b);
line 20-21 does not call the checkcast
operation4.
Hence, we can conclude that javac
remove useless cast during compilation.
Consequently, I can prevent the introduction of additional complexity in my compiler while keeping a clean and efficient bytecode.
-
But I will not discuss whether using explicit type casts is a good practice in this post. ↩︎
-
javap
documentation: https://docs.oracle.com/javase/7/docs/technotes/tools/windows/javap.html. ↩︎ -
An introduction to bytecode: https://dzone.com/articles/introduction-to-java-bytecode. ↩︎
-
checkcast
documentation: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.checkcast ↩︎