While upgrading a build from Java 1.6 to 1.7 our unit tests started failing because of a difference between how the 2 versions handle the printing of trailing zeros on doubles.
This can be reproduced with this example:
double preInit = 0.0010d;
System.out.println("pre-init: " + preInit);
System.out.println(" inline: " + 0.0010d);
Java 1.6 will output:
pre-init: 0.0010
inline: 0.0010
Java 1.7 will output:
pre-init: 0.001
inline: 0.0010
I have 2 questions:
For part 1, it turns out the difference is in how the compiler optimizes the code.
The inline case decompiles to:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22; //String inline: 0.0010
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
Operation 3 indicates that it is already pushing the String constant "inline: 0.0010" to the stack.
Compare to the pre-initialized case:
0: ldc2_w #16; //double 0.0010d
3: dstore_1
4: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
7: new #24; //class java/lang/StringBuilder
10: dup
11: ldc #26; //String pre-init:
13: invokespecial #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
16: dload_1
17: invokevirtual #31; //Method java/lang/StringBuilder.append:(D)Ljava/lang/StringBuilder;
20: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
23: invokevirtual #39; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
26: return
Operation 11 pushes the label "pre-init: " to the stack and then the following operation use a StringBuilder to append the double value.
I think the Java bug that @PM77-1 mentioned was fixed in the Java Double class but not in the compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With