Summary: | [1.5][compiler] Compiling Classpath classes results in bad class file | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
Product: | [Eclipse Project] JDT | Reporter: | Ewout Prangsma <ewout> | ||||||||
Component: | Core | Assignee: | Philipe Mulet <philippe_mulet> | ||||||||
Status: | VERIFIED FIXED | QA Contact: | |||||||||
Severity: | normal | ||||||||||
Priority: | P3 | CC: | kent_johnson, maxime_daniel, nd, Olivier_Thomann | ||||||||
Version: | 3.1 | ||||||||||
Target Milestone: | 3.1 | ||||||||||
Hardware: | PC | ||||||||||
OS: | Windows XP | ||||||||||
Whiteboard: | |||||||||||
Attachments: |
|
Description
Ewout Prangsma
2005-06-26 14:09:03 EDT
Could you please provide steps to reproduce? What version of GNU Classpath classes are you compiling? What are your compiler's settings?? For the exact classpath files, see our repository (we copy them) at: http://cvs.sourceforge.net/viewcvs.py/jnode/jnode/core/src/classpath/ It is a mix of classpath HEAD branch and the generic branch (in the 5.0 directory in our repository) The compiler settings are 5.0 source & target. See: http://cvs.sourceforge.net/viewcvs.py/jnode/jnode/core/.settings/ Ewout We have the same or similar problem!
This is a severe problem for us since all our JSP's are compiled using SUN's
javac, and our java source using the eclipse compiler.
Can be reproduced as follows:
Foo.java
public interface Foo<T> {
public T getIt();
}
FooImpl.java:
public class FooImpl implements Foo {
public String getIt() {
return null;
}
}
Bar.java
public class Bar {
public void doIt() {
Object s = new FooImpl().getIt();
}
}
Compile Foo and FooImpl using eclipse JDT compiler.
Compile Bar using SUN javac 1.5.0:
>javac Bar.java
Bar.java:5: cannot access FooImpl
bad class file: .\FooImpl.class
undeclared type variable: T
Please remove or make sure it appears in the correct subdirectory of the
classpath.
Object s = new FooImpl().getIt();
^
1 error
Using javac for all source files succeeds without errors.
Please consider changing the priority for this bug. Later scenario reproduced. It results from insertion of generic signature attribute for bridge method. First of all, the example in comment 3 is just a simple case to reproduce the bug, and easy to work around. However, in our code there are other places that are harder (or maybe even impossible) to fix. The main problem is that all our JSP files are runtime compiled using javac. Our web application is based on the usage of JSP files. Since the java code is compiled by Eclipse ande the JSP files are compiled by javac, we cannot start or debug our application from Eclipse any longer. This is a big problem. I agree this is unhappy, but given it was reported to us very late, it doesn't qualify as a stop ship issue (which it would take to get into 3.1). A workaround is to compile all files with the same compiler (either Eclipse or javac). Note that our compiler can also be used on the command line as a batch compiler. However, this should be fixed in upcoming 3.1.1. We can even post you a patch for it as soon as we have it. Would this be ok ? Rephrasing beginning of my previous comment. I agree this is unhappy, but given it was reported to us very late, it cannot be addressed for 3.1, as at this stage only stop ship issues can be addressed. Had it been reported earlier, we would have considered it. We are compromising the gain of a fix with the risk of breaking more. I understand and agree. I'll have a look into using Eclipse to compile out JSP files. We use Jasper, so technically it must be possible. Is it possible to configure Eclipse to use javac instead of the built in compiler? I am looking forward to receiving a patch. For me not having this fixed in 3.1 means that I cannot start to use 3.1 and i have to stick with 3.1M7 until it is fixed. So unhappy... certainly please submit the patch as soon as possible. Thanks Ewout Re: comment 10. No, you cannot use javac in place of Eclipse built-in compiler, other than using Ant scripts. Re: comment 11. I wonder how M7 did work for it. It was broken since ever... need to investigate. Created attachment 24024 [details]
Patch for SyntheticMethodBinding
Disable the generic signature generation for bridge methods.
(In reply to comment #13) > Created an attachment (id=24024) [edit] > Patch for SyntheticMethodBinding > > Disable the generic signature generation for bridge methods. Can you provide a compiled version. I've never build Eclipse myself (and I hope i don't have to start now) Ewout Reproduced upon initial test case. Also checked that 3.1 M7 generates different contents for String.class than 3.1 RC4 does. Differences of interest summarized in attachment. Created attachment 24033 [details]
javap differences
The patch works for us. Thank you for you quick and effective response. Problem got introduced between v_559 and v_560. Got it. Problem got introduced with fix for bug 96646. The bogus signature was tagged on the bridge method, but the corresponding attribute was never generated. Our fix therefore looks adequate, and is fully understood. Created attachment 24035 [details]
Differences between M7 and RC4 on smaller testcase
Regression tests: //https://bugs.eclipse.org/bugs/show_bug.cgi?id=101794 public void test772() { this.runConformTest( new String[] { "X.java", "interface Foo<T> {\n" + " public T getIt();\n" + "}\n" + "\n" + "class FooImpl implements Foo {\n" + " public String getIt() {\n" + " return null;\n" + " }\n" + "}\n" + "public class X {\n" + " public void doIt() {\n" + " Object s = new FooImpl().getIt();\n" + " }\n" + "}\n", }, ""); this.runConformTest( new String[] { "X.java", "public class X {\n" + " public void doIt() {\n" + " Object s = new FooImpl().getIt();\n" + " }\n" + "}\n", }, "", null, false, null); String expectedOutput = " // Method descriptor #18 ()Ljava/lang/Object;\n" + " // Stack: 1, Locals: 1\n" + " public bridge synthetic Object getIt();\n" + " 0 aload_0\n" + " 1 invokevirtual FooImpl.getIt() : java.lang.String [20]\n" + " 4 checkcast java.lang.Object [4]\n" + " 7 areturn\n" + " Line numbers:\n" + " [pc: 0, line: 1]\n"; try { File f = new File(OUTPUT_DIR + File.separator + "FooImpl.class"); byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED); int index = result.indexOf(expectedOutput); if (index == -1 || expectedOutput.length() == 0) { System.out.println(Util.displayString(result, 3)); } if (index == -1) { assertEquals("Wrong contents", expectedOutput, result); } } catch (org.eclipse.jdt.core.util.ClassFormatException e) { assertTrue(false); } catch (IOException e) { assertTrue(false); } } //https://bugs.eclipse.org/bugs/show_bug.cgi?id=101794 - variation public void test773() { this.runConformTest( new String[] { "X.java", "interface Foo<T extends Exception> {\n" + " public T getIt() throws T;\n" + "}\n" + "\n" + "class FooImpl implements Foo {\n" + " public NullPointerException getIt() {\n" + " return null;\n" + " }\n" + "}\n" + "public class X {\n" + " public void doIt() {\n" + " Object s = new FooImpl().getIt();\n" + " }\n" + "}\n", }, ""); this.runConformTest( new String[] { "X.java", "public class X {\n" + " public void doIt() {\n" + " Object s = new FooImpl().getIt();\n" + " }\n" + "}\n", }, "", null, false, null); String expectedOutput = " // Method descriptor #18 ()Ljava/lang/Exception;\n" + " // Stack: 1, Locals: 1\n" + " public bridge synthetic Exception getIt() throws java.lang.Exception;\n" + " 0 aload_0\n" + " 1 invokevirtual FooImpl.getIt() : java.lang.NullPointerException [23]\n" + " 4 checkcast java.lang.Exception [21]\n" + " 7 areturn\n" + " Line numbers:\n" + " [pc: 0, line: 1]\n"; try { File f = new File(OUTPUT_DIR + File.separator + "FooImpl.class"); byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f); ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler(); String result = disassembler.disassemble(classFileBytes, "\n", ClassFileBytesDisassembler.DETAILED); int index = result.indexOf(expectedOutput); if (index == -1 || expectedOutput.length() == 0) { System.out.println(Util.displayString(result, 3)); } if (index == -1) { assertEquals("Wrong contents", expectedOutput, result); } } catch (org.eclipse.jdt.core.util.ClassFormatException e) { assertTrue(false); } catch (IOException e) { assertTrue(false); } } Considering for 3.1 rebuild. Olivier/Kent - pls review the change Patch looks good. Verified that the bridge method compareTo doesn't have a signature attribute anymore. Verified in I20050627-1435 Reporters, could you please verify that the latest build no longer has this issue ? It seems to work fine now. Thanks for the quick response. Ewout *** Bug 102022 has been marked as a duplicate of this bug. *** |