Bug 186181 - 1.5 compiler does not understand class files built by -target jsr14
Summary: 1.5 compiler does not understand class files built by -target jsr14
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 RC1   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-05-09 11:27 EDT by John Mazzitelli CLA
Modified: 2007-05-15 05:42 EDT (History)
1 user (show)

See Also:
philippe_mulet: review+


Attachments
project that replicates the bug (3.22 KB, application/x-download)
2007-05-09 11:28 EDT, John Mazzitelli CLA
no flags Details
Proposed fix (1.93 KB, patch)
2007-05-10 15:02 EDT, Olivier Thomann CLA
no flags Details | Diff
New patch (8.56 KB, patch)
2007-05-11 11:35 EDT, Olivier Thomann CLA
no flags Details | Diff
Regression test (4.32 KB, patch)
2007-05-11 12:31 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Mazzitelli CLA 2007-05-09 11:27:42 EDT
Build ID: M20070212-1330

Steps To Reproduce:

I will attach a varargs-bug.zip that clearly replicates this problem on Eclipse 3.2.2 using SUN's JDK.

1. Unzip the attached varargs-bug.zip onto your box

2. Import the varargs-bug project into Eclipse 3.2.2

3. You should have an External Tools entry called "Build Java5 Jar" - run it (Run->ExternalTools->BuildJava5Jar).  This will do several things:
   a) it will run ANT to compile the java class found in java4-src using the -target jsr14 compiler option.  The java class (VarargClass) uses Java5 varargs but the -target option writes its .class as a 1.4 compatible class
   b) it will use ANT to bundle that 1.4 versioned class in ant-generated/java4-lib/java4.jar
   c) it will use ANT to compile the java class found in java5-src using normal 1.5 target so it is a true 1.5 versioned class (the class name is UseVararg)
   d) it will use ANT to run the main() method in UseVararg and you will see everything works fine.  UseVararg will call into the vararg method of the 1.4 versioned class and output the results of that call (",this tests that a JDK5...")

You have just verified that this is a valid thing to do (the ANT build in step 3 verified that everything works correctly if you want to run a 1.5 class that calls into a 1.4 class that uses 1.5 features but was built via -target jsr14)

4. select the vararg-bug project in your Eclipse Navigator and refresh the project (you will see the ant-generated folder and its subfolders show up - these were generated by the ANT external tool you ran in step 3)

5. Now use Eclipse to build the project (Project->BuildProject).  The Eclipse project only has a single source folder - the java5-src.  The Eclipse project only has a single jar in its build path - that being the ant-generated/java-lib/java4.jar which contains the class built via the -target jsr14 option.

Notice Eclipse compiler complains about the call into the 1.4 versioned class's vararg method:

The method varargMethod(Object[]) in the type VarargClass is not applicable for the arguments (String)	vararg-bug/java5-src	UseVararg.java	line 6

This should be allowed, as demonstrated by step 3 when building and running using a non-Eclipse compiler.

My JDK version is:

> java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)

My OS is Windows XP SP2.

More information:

This is not really related to Bug 107783 - I am not asking Eclipse's 1.5 compiler to generate 1.4 versioned classes. I am only asking Eclipse's 1.5 compiler to understand 1.4 classes generated via the -target jsr14 option.
Comment 1 John Mazzitelli CLA 2007-05-09 11:28:53 EDT
Created attachment 66492 [details]
project that replicates the bug

See "steps to reproduce" in bug description to know what to do with the attached .zip file in order to replicate the bug.
Comment 2 Matt Chapman CLA 2007-05-10 03:44:49 EDT
Passing over to JDT
Comment 3 Olivier Thomann CLA 2007-05-10 14:30:35 EDT
This is because javac knows how to read the attribute called Varargs and we don't.
When you compile your class with target jsr14, instead of setting a bit to ACC_VARARGS(0x0080) javac decides to add a new (unspecified) attribute called Varargs to tag the method as a vararg method.
Then when javac reads back the .class file that contains this method, it can recognize that this is a varargs method.
The Eclipse compiler doesn't recognize the varargs attribute and therefore doesn't know what it means. The method is not tagged as a vararg method and the code doesn't compile.
The worksaround is to wrap your parameter in an array.
Note that javac 1.4.2 also reports the same issue:
X.java:4: varargMethod(java.lang.Object[]) in VarargClass cannot be applied to (java.lang.String)
      String results = VarargClass.varargMethod(arg);
                                  ^
1 error

So your code won't compile anyway with a 1.4 compiler. If you set javac 1.5 to compile in 1.4 mode, you also cannot compile the code:

d:\tests_sources>javac X.java -classpath java4.jar -target 1.4 -source 1.4
X.java:4: varargMethod(java.lang.Object[]) in VarargClass cannot be applied to (java.lang.String)
      String results = VarargClass.varargMethod(arg);
                                  ^
1 error

d:\tests_sources>javac X.java -classpath java4.jar -target jsr14 -source 1.4
X.java:4: varargMethod(java.lang.Object[]) in VarargClass cannot be applied to (java.lang.String)
      String results = VarargClass.varargMethod(arg);
                                  ^
1 error

So from my point of view, there is no point of compiling using jsr14, if you then need to compile with target and source to 1.5 in order to be able to use the varargs methods as a varargs method. Why not compiling everything in target 1.5 and then you would not have a problem reported by the Eclipse compiler?

If you wrap your parameter inside an array of String, the code compiles fine and in this case you would not need this special attribute.

Philippe, do you think we should handle this case?
Comment 4 Olivier Thomann CLA 2007-05-10 15:02:16 EDT
Created attachment 66747 [details]
Proposed fix

The fix is absolutely trivial.
Comment 5 John Mazzitelli CLA 2007-05-10 15:25:16 EDT
nice - can I assume that when you say, "the fix is absolutely trivial" that it is equally trivial to put the fix in the next Eclipse release? :-)
Comment 6 Olivier Thomann CLA 2007-05-10 15:29:33 EDT
This is getting late in the game.
Philippe, do you believe we should fix this one?
It might improve our support for users that are mixed between 1.4 and 1.5. The fix is a no risk fix.
Comment 7 Olivier Thomann CLA 2007-05-10 18:59:16 EDT
We don't generate the attribute when the Eclipse batch compiler is used with target 1.4. And this doesn't prevent the resulting .class file from being run on a 1.4 VM.
I could emulate the same attribute, but I don't feel this is necessary. We might just want to keep the support to read it.
Comment 8 Philipe Mulet CLA 2007-05-11 03:57:43 EDT
I think if we support reading the attribute, we should also support writing it (in -target jsr14 mode only); so we can consume our output.

Is this behavior spec'ed anywhere, or is this a javac hack we would try to mimic ?
Comment 9 Philipe Mulet CLA 2007-05-11 03:58:55 EDT
Re: comment 8 "(in -target jsr14 mode only)"
I think this simply means technically if target is 1.4 as you said earlier Olivier.
Comment 10 Olivier Thomann CLA 2007-05-11 11:04:06 EDT
I'll prepare a patch for 3.3RC1 that will also include the generation of this attribute.
Comment 11 Olivier Thomann CLA 2007-05-11 11:35:36 EDT
Created attachment 66881 [details]
New patch

This new patch:
- read the Varargs attribute from existing .class file (compiled with Eclipse compiler or javac using target jsr14)
- generate the Varargs attribute if the code is compiled with target jsr14. This is done by clearing the bit from the access flags of the method info and adding an attribute.
- update the disassembler to also recognize the new attribute.
Comment 12 Olivier Thomann CLA 2007-05-11 11:35:58 EDT
Philippe, please review.
Comment 13 Olivier Thomann CLA 2007-05-11 12:31:55 EDT
Created attachment 66898 [details]
Regression test
Comment 14 Olivier Thomann CLA 2007-05-11 14:19:40 EDT
Released for 3.3RC1.
Comment 15 John Mazzitelli CLA 2007-05-11 14:22:21 EDT
thanks for the quick turnaround
Comment 16 Olivier Thomann CLA 2007-05-11 17:21:50 EDT
No problem. When the fix is that simple and has no impact on "normal" use case and provide a good value, then it is ok to fix it now.
I encourage you to try the next integration build or 3.3RC1 build and confirm that this is fixed. Thank you.
Comment 17 Olivier Thomann CLA 2007-05-11 18:21:40 EDT
Regression test is:
org.eclipse.jdt.core.tests.compiler.regression.VarargsTest#test060
Comment 18 Frederic Fusier CLA 2007-05-15 05:42:32 EDT
Verified for 3.3 RC1 using I20070515-0010