Bug 148807 - [compiler] code generation: Eclipse compiler creates class files that produce VerifyError when run with 1.4 VM
Summary: [compiler] code generation: Eclipse compiler creates class files that produce...
Status: RESOLVED WONTFIX
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Linux-GTK
: P3 normal (vote)
Target Milestone: 3.3 M1   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-06-27 09:08 EDT by Tom Hofmann CLA
Modified: 2006-06-28 03:30 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Hofmann CLA 2006-06-27 09:08:56 EDT
I20060620

- have the snippet below
- compile with Java source version == 1.4
- run with a 1.4 VM (tested Sun and IBM)
-> VerifyError is thrown (full stack trace below)

- run with a 1.5 VM
-> ArrayStoreException as expected

---------- Main.java ---------------
package pack;

public class Main {
    public static void main(String[] args) {
	Object[][] all = new String[1][];
	all[0] = new Object[0];
    }
}
------------------------------------

Exception in thread "main" java.lang.VerifyError: (class: pack/Main, method: main signature: ([Ljava/lang/String;)V) Incompatible types for storing into array of arrays or objects
Comment 1 Philipe Mulet CLA 2006-06-27 09:40:08 EDT
Same behavior as javac.

Note that our bytecode is suboptimal. We always use multianewarray where we could use newarray when only one explicit dimension.
Comment 2 Markus Keller CLA 2006-06-27 10:00:02 EDT
Looks like the vmspec has been changed in 1.5 to accomodate for this problem.

The aastore instruction tries to store a [Object into a [[String, which is not allowed by the vmspec, 2nd ed., 4.8.2: "The type of every value stored into an array of type reference by an aastore instruction must be assignment compatible (ยง2.6.7) with the component type of the array."

In the 1.5 changes to the classfile format, 4.10.2, this has been changed to: "The type of every value stored into an array by an aastore instruction must be
a reference type. The component type of the array being stored into by the aastore instruction must also be a reference type."

I guess it would be quite hard to prevent this problem in 1.4. The only way I see would be be to generate different bytecode which e.g. introduces a synthetic method to ensure that the local variable 'all' has type [[Object. But that would not be bug-compatible to JDK1.4 any more...
Comment 3 Markus Keller CLA 2006-06-27 10:31:15 EDT
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4368664 sounds similar, but the resolution in Sun's database is unclear to me...

However, i noticed that javac1.4.2_11 emits a "checkcast[[Ljava/lang/Object;" when the second line is changed to "((Object[][]) all)[0]= new Object[0];". This avoids the VerifyError. The eclipse compiler does not emit the (theoretically redundant) checkcast.
Comment 4 Philipe Mulet CLA 2006-06-27 10:32:42 EDT
We could insert a checkcast to workaround the issue in the 1.4 verifier; but this would alter the runtime behavior in presence of a type mismatch (classcast instead of arraystore).

I would still address the suboptimal bytecode in array allocation, and leave the VM issue as a VM issue.
Comment 5 Philipe Mulet CLA 2006-06-27 12:08:36 EDT
No action planned. Entered ArrayTest#test011-013.
Verifier bug only occurs in invalid code (which would throw ArrayStoreException at runtime).
Comment 6 Tom Hofmann CLA 2006-06-28 02:32:32 EDT
(In reply to comment #5)
> Verifier bug only occurs in invalid code (which would throw 
> ArrayStoreException at runtime).

Don't want to be witty, but: the following will compile fine and run without a problem on a Java5 VM, but throw a VerifyError on a 1.4 VM (compiled with either javac or ecj):

---------- Main.java ---------------
package pack;

public class Main {
    public static void main(String[] args) {
        Object[][] all = new String[1][];
        all[0] = getObjs();
    }

    static Object[] getObjs() {
         return new String[0];
    }
}
------------------------------------

Comment 7 Philipe Mulet CLA 2006-06-28 03:30:07 EDT
Good point Tom. My previous post should have said that it works fine unless clients do mix array types (which I incorrectly assumed would lead to invalid case). The verifier is doing value propagation (per essence) where the compiler relies on statically declared types, and thus would need to protect code which is running fine today, and insert extra checkcast, which additionally would change the runtime behavior (not the same runtime exception in case of trouble).