Bug 101794 - [1.5][compiler] Compiling Classpath classes results in bad class file
Summary: [1.5][compiler] Compiling Classpath classes results in bad class file
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 102022 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-06-26 14:09 EDT by Ewout Prangsma CLA
Modified: 2005-06-28 12:02 EDT (History)
4 users (show)

See Also:


Attachments
Patch for SyntheticMethodBinding (1.17 KB, patch)
2005-06-27 07:52 EDT, Philipe Mulet CLA
no flags Details | Diff
javap differences (1.80 KB, text/plain)
2005-06-27 10:37 EDT, Maxime Daniel CLA
no flags Details
Differences between M7 and RC4 on smaller testcase (1.84 KB, text/plain)
2005-06-27 11:30 EDT, Maxime Daniel CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ewout Prangsma CLA 2005-06-26 14:09:03 EDT
I've compiled the classes from classpath.org with Eclipse 3.1RC3 and RC4 and on
both, once I want to use the classes in the Sun JVM, I got the following message:

compile:
[jnode.compile] Compiling 4 source files to D:\epr\cvswork\jnode\core\build\clas
ses
[jnode.compile] D:\epr\cvswork\jnode\core\build\gen\org\jnode\test\PrimitiveDoub
leTest.java:11: cannot access java.lang.String
[jnode.compile] bad class file: D:\epr\cvswork\jnode\core\build\classes\java\lan
g\String.class
[jnode.compile] undeclared type variable: T
[jnode.compile] Please remove or make sure it appears in the correct subdirector
y of the classpath.
[jnode.compile]         public static void main(String [] args) {
[jnode.compile]                                 ^
[jnode.compile] 1 error


This problem did not occur in 3.1-M7 and before.

Ewout
Comment 1 Olivier Thomann CLA 2005-06-26 18:38:01 EDT
Could you please provide steps to reproduce?
What version of GNU Classpath classes are you compiling?
What are your compiler's settings??
Comment 2 Ewout Prangsma CLA 2005-06-27 02:20:09 EDT
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
Comment 3 Martijn Vogten CLA 2005-06-27 05:31:08 EDT
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.
Comment 4 Roel Spilker CLA 2005-06-27 05:39:48 EDT
Please consider changing the priority for this bug.
Comment 5 Philipe Mulet CLA 2005-06-27 05:52:53 EDT
Later scenario reproduced. It results from insertion of generic signature
attribute for bridge method.
Comment 6 Philipe Mulet CLA 2005-06-27 05:54:24 EDT
Re: comment 4: why ?
Comment 7 Roel Spilker CLA 2005-06-27 06:38:04 EDT
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.



Comment 8 Philipe Mulet CLA 2005-06-27 07:34:36 EDT
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 ?
Comment 9 Philipe Mulet CLA 2005-06-27 07:37:08 EDT
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.
Comment 10 Roel Spilker CLA 2005-06-27 07:49:18 EDT
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.
Comment 11 Ewout Prangsma CLA 2005-06-27 07:49:41 EDT
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
Comment 12 Philipe Mulet CLA 2005-06-27 07:51:50 EDT
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.
Comment 13 Philipe Mulet CLA 2005-06-27 07:52:36 EDT
Created attachment 24024 [details]
Patch for SyntheticMethodBinding

Disable the generic signature generation for bridge methods.
Comment 14 Ewout Prangsma CLA 2005-06-27 08:59:30 EDT
(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
Comment 15 Maxime Daniel CLA 2005-06-27 10:31:52 EDT
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.
Comment 16 Maxime Daniel CLA 2005-06-27 10:37:03 EDT
Created attachment 24033 [details]
javap differences
Comment 17 Roel Spilker CLA 2005-06-27 10:59:58 EDT
The patch works for us. Thank you for you quick and effective response.
Comment 18 Philipe Mulet CLA 2005-06-27 11:23:10 EDT
Problem got introduced between v_559 and v_560.
Comment 19 Philipe Mulet CLA 2005-06-27 11:30:25 EDT
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.
Comment 20 Maxime Daniel CLA 2005-06-27 11:30:36 EDT
Created attachment 24035 [details]
Differences between M7 and RC4 on smaller testcase
Comment 21 Philipe Mulet CLA 2005-06-27 11:32:25 EDT
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);
		}	
}
Comment 22 Philipe Mulet CLA 2005-06-27 12:13:19 EDT
Considering for 3.1 rebuild.
Comment 23 Philipe Mulet CLA 2005-06-27 13:11:09 EDT
Olivier/Kent - pls review the change
Comment 24 Olivier Thomann CLA 2005-06-27 13:12:15 EDT
Patch looks good.
Comment 25 Olivier Thomann CLA 2005-06-27 16:14:52 EDT
Verified that the bridge method compareTo doesn't have a signature attribute
anymore.
Verified in I20050627-1435
Comment 26 Philipe Mulet CLA 2005-06-28 03:11:37 EDT
Reporters, could you please verify that the latest build no longer has this issue ?
Comment 27 Ewout Prangsma CLA 2005-06-28 08:39:23 EDT
It seems to work fine now.

Thanks for the quick response.

Ewout
Comment 28 Philipe Mulet CLA 2005-06-28 12:02:03 EDT
*** Bug 102022 has been marked as a duplicate of this bug. ***