Community
Participate
Working Groups
I am including a sample set of classes that demonstrate the error. Compiling these classes on the commandline with Sun's compiler and running Main works (I have used 1.3, 1.4.1_01, and 1.4.2_02, all on Win2000 and WinXP). Compiling these classes in Eclipse 3.0M5 and running Main inside the environment or on the commandline throws an ExceptionInInitializerError because ClassOne doesn't exist yet. Please let me know if you need more information. ****** ClassOne.java ****** public class ClassOne { static { StaticCollection.COLLECTION.add(ClassOne.class); } } ****** ClassTwo.java ****** public class ClassTwo { static { if (!StaticCollection.COLLECTION.contains(ClassOne.class)) { throw new RuntimeException("ClassOne doesn't exist"); } } } ****** StaticCollection.java ****** import java.util.ArrayList; import java.util.Collection; public class StaticCollection { public final static Collection COLLECTION = new ArrayList(); } ****** Main.java ****** public class Main { public static void main(String[] args) { System.out.println(new ClassTwo()); System.exit(0); } }
This is a consequence of the fix for bug 37565. Your code relies on the fact that the class literal initializes the class. This should not be the case as long as the JLS doesn't state it. The bug is on the javac side. Jikes behaves the same way we do.
So, can you provide a backward compatibility preference? It is my assumption (through 5 years of Java experience) that most developers rely "on the fact that the class literal initializes the class." This change would certainly break the last 5 projects I have been on, and of course breaks the project I am currently on. This seems like more of a dis-service to your community than a service.
Olivier, couldn't we trigger the initialization in 1.3 compliant mode, and avoid it only in 1.4 mode where modern compilers have moved (or are going to move) ? Jason, would this work for you ?
This is easily doable. If we do it, it should be documented. My concern is that javac 1.4 still has the bug. I don't know if they will fix compiler or update the specs.
I don't think we need to be backward compatible with a bug.
Although that won't work for my current project I believe that is a good compromise. I would thus disagree with Olivier in that he thinks we don't need to be backward-compatible. As I said before, I believe much of the community is probably depending on this behavior... Do you really want to upset a good percentage of the community?
The purpose of the comment 5 is not to upset anybody. I was simply saying that this behavior is boggus and doesn't follow the JLS. If anybody is using jikes to compile the code, it won't work as expected. The "right" behavior of the compiler is the one that doesn't initialize the class. The JLS might be updated to add the class literal as one of the condition for class initialization. It is not the case for now. I have the code ready to move back to the previous behavior if compliance is 1.3.
Problem here is just another instance of spec saying something, and some compiler implementations behaving differently... so both positions are valid...
We are reverting to the old behavior where the class literal will initialize the class. The reason is that too much code relies on this wrong behavior and as long as javac has not changed, we cannot change it. This can be reopen once the JLS revision (version 3.0) states what should be done in this case. Regression test added.
Verified for 3.0M6