There is a serious error in the JDK 1.5 compiler, pointed out to me by one of my readers (of The Java Specialists' Newsletter), Amotz Anner.
Amotz has submitted a bug report already to Sun, and as soon as we have a number from Sun (may take up to three weeks) we will post that in a follow-up.
Here is the problem:
final String name = false ? "Heinz" : null;
System.out.println(name);
When compiled using the JDK 1.5 compiler, it will print out "Heinz". It does not matter whether you say -source 1.[234] or whether you run it using any of the JDK 1.[2345].x JVMs from Sun.
This happens only when the local variable is set to "final" and one of the values of the ternary if-else is literal null.
PLEASE let's not make this into a mud-slinging match against Sun Microsystems, ok? They are overloaded with bug reports as it is. The reason that I post this is to make you aware to NOT use the final local variables in combination with ternary if-else until further notice. You might not be compiling with JDK 1.5, but one of your colleagues might.
What are your favorite JVM bugs? :)
-
Nasty Little JDK 1.5 Compiler Bug: final + ternary (31 messages)
- Posted by: Heinz Kabutz
- Posted on: October 12 2004 16:53 EDT
Threaded Messages (31)
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by shawn spencer on October 13 2004 13:33 EDT
- How not to be informative by glen martin on October 13 2004 16:30 EDT
- How not to be informative by Heinz Kabutz on October 13 2004 04:48 EDT
- jdk "bugzilla" by Conrad Roche on October 13 2004 05:13 EDT
- Maybe.. by Nathan Lee on October 14 2004 11:03 EDT
- How not to be informative by glen martin on October 13 2004 16:30 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Nils Kilden-Pedersen on October 13 2004 16:45 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Heinz Kabutz on October 13 2004 16:51 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Heinz Kabutz on October 14 2004 03:21 EDT
- Bug not apparent in the Linux VM by Greg Hall on October 14 2004 04:05 EDT
- The BUG does exist by Bin Sun on October 13 2004 22:21 EDT
- The BUG does exist by Steven Devijver on October 14 2004 02:41 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Heinz Kabutz on October 13 2004 16:51 EDT
- Nasty? I think not by John Davies on October 13 2004 17:05 EDT
- RE: Nasty? I think not by Kelsey Grant on October 13 2004 22:02 EDT
- RE: Nasty? I think not by John Davies on October 13 2004 10:35 EDT
- Nasty? I think not by Heinz Kabutz on October 14 2004 03:15 EDT
- Nasty? I think not by peter jodeleit on October 14 2004 05:36 EDT
-
Nasty? I think not by bruno chevalier on October 14 2004 06:59 EDT
-
Nasty? I think not by Yevgeny Libman on October 14 2004 09:26 EDT
- It's getting more interesting while looking at generated code... by Vitaliy Stulski on October 14 2004 10:10 EDT
- Nasty? I think not by Heinz Kabutz on October 15 2004 01:58 EDT
-
Nasty? I think not by Yevgeny Libman on October 14 2004 09:26 EDT
-
Guarding Against Null by Michael Kolb on October 14 2004 10:42 EDT
- Confirmed With 1.5.0 beta by Michael Kolb on October 14 2004 10:58 EDT
-
Nasty? I think not by bruno chevalier on October 14 2004 06:59 EDT
- RE: Nasty? I think not by Kelsey Grant on October 13 2004 22:02 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary. by Thai Dang Vu on October 13 2004 20:19 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary. by wang zaixiang on October 13 2004 21:05 EDT
- Don't understand by bruno chevalier on October 14 2004 03:12 EDT
- Don't understand by bruno chevalier on October 14 2004 03:15 EDT
- Don't understand by Jonathan Knight on October 14 2004 03:53 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by han theman on October 14 2004 04:15 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Heinz Kabutz on October 14 2004 05:18 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by han theman on October 14 2004 08:24 EDT
- Nasty Little JDK 1.5 Compiler Bug: final + ternary by Heinz Kabutz on October 14 2004 05:18 EDT
- works ok on NT 4.0 by Alex Wouda on October 15 2004 04:38 EDT
-
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: shawn spencer
- Posted on: October 13 2004 13:33 EDT
- in response to Heinz Kabutz
I m sure there is a jdk 1.5.(x+1) on the way. nothing is perfect in first shot. 1.4 itself is going thru so many versions as we speak.
But this will be a good thread to make a list of all issues for the dev community to know.
Its just a bit too early i guess - not a lot of us have gives a test drive to 1.5 yet to this extent. -
How not to be informative[ Go to top ]
- Posted by: glen martin
- Posted on: October 13 2004 16:30 EDT
- in response to shawn spencer
But this will be a good thread to make a list of all issues for the dev community to know.
No, it wouldn't. This is a lousy place. A week from now, this discussion will be buried under any number of other discussions on this site, and folks either won't see it and learn about a bug, or won't see and add their bugs. If informing the developer community of bugs is important (and I'll provisionally agree that it is), then do a good job of it.
Additionally, a threaded discussion isn't a good way to *list* problems. That's what tools like bugzilla, or even a simple tabular list of links, is good for. Threaded discussions are to *discuss* things. To carry on conversations.
I applaud the original poster's plea to not turn this into a mudslinging match. I imagine he didn't include the final line of that post, "What's your favorite JVM bug?" That sounds to me like an attempt to inspire exactly the sort of mudslinging he argued against. (Perhaps he did write that comment, and meant it another way, in which case I apologise for my suspicious mind).
Disclosure: I don't work for Sun, but I used to. -
How not to be informative[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 13 2004 16:48 EDT
- in response to glen martin
I imagine he didn't include the final line of that post, "What's your favorite JVM bug?" That sounds to me like an attempt to inspire exactly the sort of mudslinging he argued against. (Perhaps he did write that comment, and meant it another way, in which case I apologise for my suspicious mind)
Well spotted Glen, that line was certainly not put in by me. Must have been one of the editors ... (let's not start mudslinging them either... ;-)
On the JavaLobby site, someone posted a link to a bug report on the JavaSoft site. It looks like that bug will be gone in the next release, but be careful - it also applies to final fields as well as local variables.
For the record, the URL for the bug tracking is http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5105890
Heinz -
jdk "bugzilla"[ Go to top ]
- Posted by: Conrad Roche
- Posted on: October 13 2004 17:13 EDT
- in response to glen martin
There is a "bugzilla" already available for the jdk - just go toBut this will be a good thread to make a list of all issues for the dev community to know.
Additionally, a threaded discussion isn't a good way to *list* problems. That's what tools like bugzilla, or even a simple tabular list of links, is good for.
http://bugs.sun.com/bugdatabase/search.do?action=1&category=java&bugStatus=&keyword=1.5&maxResults=10&startIndex=1&sortBy=relevance -
Maybe..[ Go to top ]
- Posted by: Nathan Lee
- Posted on: October 14 2004 11:03 EDT
- in response to shawn spencer
.. it's an attempt to deprecate those bloody ternary operators that allow people to produce nice concise unreadable code ;)
Nath -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: Nils Kilden-Pedersen
- Posted on: October 13 2004 16:45 EDT
- in response to Heinz Kabutz
final String name = false ? "Heinz" : null;
Not here. I get null. Are you sure you're using 1.5.0 final release?
System.out.println(name);
When compiled using the JDK 1.5 compiler, it will print out "Heinz". -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 13 2004 16:51 EDT
- in response to Nils Kilden-Pedersen
Yes, as far as I know I am. Here is the version information:final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz".
Not here. I get null. Are you sure you're using 1.5.0 final release?
java version "1.5.0"<br>
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)<br>
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)<br>
I will download another version now to compare.
Make sure that you compile it with the JDK 1.5 compiler, don't use your IDE, such as Eclipse. The bug is in the compiler, not the JVM.
Heinz -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 14 2004 03:21 EDT
- in response to Heinz Kabutz
Yes, I downloaded the latest version again, and it is the same as I had.final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz".
Not here. I get null. Are you sure you're using 1.5.0 final release?
Good news - Sun have fixed this bug and it will be in the next release at the end of the year! -
Bug not apparent in the Linux VM[ Go to top ]
- Posted by: Greg Hall
- Posted on: October 14 2004 04:05 EDT
- in response to Heinz Kabutz
I compiled and ran this code on the Linux version of the Sun VM (1.5.0-b64) and it works fine (i.e. returns null).
Maybe it only affects Windows VM's.
Greg -
The BUG does exist[ Go to top ]
- Posted by: Bin Sun
- Posted on: October 13 2004 22:21 EDT
- in response to Nils Kilden-Pedersen
I got "Heinz" with JDK 5.0 final.final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz".
Not here. I get null. Are you sure you're using 1.5.0 final release?
Decompiling with JAD, I got:
// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: Test.java
import java.io.PrintStream;
public class Test
{
public Test()
{
}
public static transient void main(String args[])
throws Exception
{
String name = (String)null;
System.out.println("Heinz");
}
} -
The BUG does exist[ Go to top ]
- Posted by: Steven Devijver
- Posted on: October 14 2004 02:41 EDT
- in response to Bin Sun
That looks final to me. Static transient? -
Nasty? I think not[ Go to top ]
- Posted by: John Davies
- Posted on: October 13 2004 17:05 EDT
- in response to Heinz Kabutz
final String name = false ? "Heinz" : null;
So basically it won't compile obfuscated code? Not exactly "nasty".
Seriously, this is not a great piece of code, I agree it should work and that this is indeed a bug but I wouldn't have accepted this if I'd seen it in one of my team's code.
-John- -
RE: Nasty? I think not[ Go to top ]
- Posted by: Kelsey Grant
- Posted on: October 13 2004 22:02 EDT
- in response to John Davies
Hmmm. Ternary statements are so maligned. The corresponding code in an if block is IMHO more difficult to read.final String name = false ? "Heinz" : null;
So basically it won't compile obfuscated code? Not exactly "nasty".Seriously, this is not a great piece of code, I agree it should work and that this is indeed a bug but I wouldn't have accepted this if I'd seen it in one of my team's code.-John-
They do also get a lot of brownie points for using final in the variable declaration, love them finals! -
RE: Nasty? I think not[ Go to top ]
- Posted by: John Davies
- Posted on: October 13 2004 22:35 EDT
- in response to Kelsey Grant
Hmmm. Ternary statements are so maligned. The corresponding code in an if block is IMHO more difficult to read.
Ternary statements are good in many cases I agree, finals are very good in all applicable places but this just doesn't look right. I'll accept that it's certainly not the worst thing I've ever seen but I'm not sure you should really put logic (ternary statements) into code initialisation. Before we get into an argument about the fact that non-finals can't be used in inner classes or that you can only initialise a final at declaration etc. my point was simply that this is not "run of the mill" code and could be simplified.
They do also get a lot of brownie points for using final in the variable declaration, love them finals!
I'll leave it that, I agree it's a bug but not one I'm going to worry too much about, thanks for pointing it out though.
-John- -
Nasty? I think not[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 14 2004 03:15 EDT
- in response to John Davies
Comeon John. That was the simplest example that could show the bug.final String name = false ? "Heinz" : null;
Seriously, this is not a great piece of code, I agree it should work and that this is indeed a bug but I wouldn't have accepted this if I'd seen it in one of my team's code.-John- -
Nasty? I think not[ Go to top ]
- Posted by: peter jodeleit
- Posted on: October 14 2004 05:36 EDT
- in response to John Davies
Just rewrite the code:final String name = false ? "Heinz" : null;
So basically it won't compile obfuscated code? Not exactly "nasty".Seriously, this is not a great piece of code, I agree it should work and that this is indeed a bug but I wouldn't have accepted this if I'd seen it in one of my team's code.final String name = getBoolean() ? "Heinz" : null;
Regardless of the result of "getBoolean()", "name" will always be "Heinz".
I woudn't qulify this code as "nasty". -
Nasty? I think not[ Go to top ]
- Posted by: bruno chevalier
- Posted on: October 14 2004 06:59 EDT
- in response to peter jodeleit
Thanks, it helps to understand the example.
This case should not occur a lot and I guess Sun will soon correct this point in the upcomming release. -
Nasty? I think not[ Go to top ]
- Posted by: Yevgeny Libman
- Posted on: October 14 2004 21:26 EDT
- in response to bruno chevalier
If using non-null initializers, like:
static final String name = false ? "Heinz": "John";
it seems to work Ok. -
It's getting more interesting while looking at generated code...[ Go to top ]
- Posted by: Vitaliy Stulski
- Posted on: October 14 2004 22:10 EDT
- in response to Yevgeny Libman
If you'll compile it without -g compiler generates just:
System.out.println("Heinz");
In case of -g flag it is being compiled into:
name = null;
System.out.println("Heinz"); -
Nasty? I think not[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 15 2004 01:58 EDT
- in response to Yevgeny Libman
If using non-null initializers, like: static final String name = false ? "Heinz": "John";it seems to work Ok.
Yip, that is right. The bug happens when one side is null. Also, if it is nonfinal, it also works correctly. -
Guarding Against Null[ Go to top ]
- Posted by: Michael Kolb
- Posted on: October 14 2004 10:42 EDT
- in response to peter jodeleit
I know I often use the following to guard against null.
Just rewrite the code:final String name = false ? "Heinz" : null;
So basically it won't compile obfuscated code? Not exactly "nasty".Seriously, this is not a great piece of code, I agree it should work and that this is indeed a bug but I wouldn't have accepted this if I'd seen it in one of my team's code.final String name = getBoolean() ? "Heinz" : null;
Regardless of the result of "getBoolean()", "name" will always be "Heinz".I woudn't qulify this code as "nasty".
<code>
final String partName = (null == part ? null : part.getName());
</code>
It sounds like a lot of my code would be broken. -
Confirmed With 1.5.0 beta[ Go to top ]
- Posted by: Michael Kolb
- Posted on: October 14 2004 10:58 EDT
- in response to Michael Kolb
I don't have the final release installed, but I have confirmed that the bug does exist in the beta.public class CompilerBugTest {
I think I'm going to add test case for this in to our project's suite to guard against it affecting us.
public static void main (String [] args) {
final String foo = (false ? "a" : null);
System.out.println("foo = " + foo);
}
}
$ /cygdrive/c/Program\ Files/Java/j2sdk1.5.0/bin/javac -version CompilerBugTest
.java
javac 1.5.0-beta
$ java CompilerBugTest
foo = a -
Nasty Little JDK 1.5 Compiler Bug: final + ternary.[ Go to top ]
- Posted by: Thai Dang Vu
- Posted on: October 13 2004 20:19 EDT
- in response to Heinz Kabutz
It's so strange. If I compile that block of code in Textpad (which I am so sure that uses the Jave 1.5.0 I installed on my machine), it prints "null". But when I compile and run it in the DOS prompt windows, it prints "Heinz". So where does the problem lie? I'm using Window$ XP Pro SP2. I haven't tested it on Linux yet. -
Nasty Little JDK 1.5 Compiler Bug: final + ternary.[ Go to top ]
- Posted by: wang zaixiang
- Posted on: October 13 2004 21:05 EDT
- in response to Thai Dang Vu
It's so strange. If I compile that block of code in Textpad (which I am so sure that uses the Jave 1.5.0 I installed on my machine), it prints "null". But when I compile and run it in the DOS prompt windows, it prints "Heinz". So where does the problem lie? I'm using Window$ XP Pro SP2. I haven't tested it on Linux yet.
Maybe you need to check your classpath setting and which makes you a mistake.
I cant understand the mistake if i code the compiler, i think it is impossible for such a big error.
As the Texpad(i dont know what it is, maybe a simple IDE) can run the program correctly, so it will.
Another more things to check:
1. please add the following statement into your code
System.out.println( getClass().getProtectionDomain().getCodeSource().getLocation() );
2. check it is the classpath that your javac compile to
3. if not, it is your problem yourself -
Don't understand[ Go to top ]
- Posted by: bruno chevalier
- Posted on: October 14 2004 03:12 EDT
- in response to Heinz Kabutz
final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz
I don't understand the interest of this code.
Ca -
Don't understand[ Go to top ]
- Posted by: bruno chevalier
- Posted on: October 14 2004 03:15 EDT
- in response to Heinz Kabutz
final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz
I don't understand the interest of this code.
Usually you use the final word to instantiate constants.
So something like final String name="Heinz";
What is the interest to test a String like a boolean, especially with the final keyword.
Can you explain in which case you are using this? -
Don't understand[ Go to top ]
- Posted by: Jonathan Knight
- Posted on: October 14 2004 03:53 EDT
- in response to bruno chevalier
You also use final if you then want to use that variable inside an anonymous inner class or something like that.final String name = false ? "Heinz" : null;System.out.println(name);When compiled using the JDK 1.5 compiler, it will print out "Heinz
I don't understand the interest of this code.Usually you use the final word to instantiate constants.So something like final String name="Heinz";What is the interest to test a String like a boolean, especially with the final keyword.Can you explain in which case you are using this?
E.G.
final String name = false?"Heinz":null;
...
Thread t = new Thread(new Runnable()
{
public void run()
{
... use the name variable in this method ...
}
});
t.start(); -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: han theman
- Posted on: October 14 2004 04:15 EDT
- in response to Heinz Kabutz
Ran it on Win xp JDK 1.5 final release.
Indeed, it returns null... weird. -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: Heinz Kabutz
- Posted on: October 14 2004 05:18 EDT
- in response to han theman
Ran it on Win xp JDK 1.5 final release.Indeed, it returns null... weird.
Did you also compile it with JDK 1.5 javac? The bug is in the compiler, not the JVM. -
Nasty Little JDK 1.5 Compiler Bug: final + ternary[ Go to top ]
- Posted by: han theman
- Posted on: October 14 2004 08:24 EDT
- in response to Heinz Kabutz
Of course I compiled it with the JDK 1.5 javac.Ran it on Win xp JDK 1.5 final release.Indeed, it returns null... weird.
Did you also compile it with JDK 1.5 javac? The bug is in the compiler, not the JVM. -
works ok on NT 4.0[ Go to top ]
- Posted by: Alex Wouda
- Posted on: October 15 2004 04:38 EDT
- in response to Heinz Kabutz
at work, using a NT4.0 sp6 machine, it works ok.
the javac -version does not exist in my jdk 1.5 version.....