Bug 48086 - Compiler does not resolve references in static init blocks correctly
Summary: Compiler does not resolve references in static init blocks correctly
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P3 critical (vote)
Target Milestone: 3.0 M6   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-12-04 11:43 EST by Jason Rogers CLA
Modified: 2003-12-17 07:19 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Rogers CLA 2003-12-04 11:43:18 EST
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);
    }
}
Comment 1 Olivier Thomann CLA 2003-12-04 12:16:41 EST
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.
Comment 2 Jason Rogers CLA 2003-12-04 14:24:29 EST
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.
Comment 3 Philipe Mulet CLA 2003-12-04 15:34:41 EST
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 ?
Comment 4 Olivier Thomann CLA 2003-12-04 16:06:18 EST
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.
Comment 5 Olivier Thomann CLA 2003-12-04 16:07:05 EST
I don't think we need to be backward compatible with a bug.
Comment 6 Jason Rogers CLA 2003-12-04 16:12:15 EST
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?
Comment 7 Olivier Thomann CLA 2003-12-04 22:17:05 EST
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.
Comment 8 Philipe Mulet CLA 2003-12-05 05:17:59 EST
Problem here is just another instance of spec saying something, and some 
compiler implementations behaving differently... so both positions are valid...
Comment 9 Olivier Thomann CLA 2003-12-05 09:52:14 EST
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.
Comment 10 David Audel CLA 2003-12-17 07:19:34 EST
Verified for 3.0M6