Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8044198 | 9 | Paul Govereau | P4 | Closed | Fixed | b16 |
JDK-8048468 | 8u25 | Paul Govereau | P4 | Resolved | Fixed | b05 |
JDK-8052615 | emb-8u26 | Paul Govereau | P4 | Resolved | Fixed | b17 |
FULL PRODUCT VERSION :
Tested on OpenJDK 7 and seen the same bug in OpenJDK 8 source code
ADDITIONAL OS VERSION INFORMATION :
Irrelevant: this is generic code
A DESCRIPTION OF THE PROBLEM :
The following code compiles but fails to run:
class Foo<Outer> {
void m(){
class Local1{}
class Local2 extends Local1{}
Local2.class.getTypeParameters();
}
public static void main(String[] args) {
new Foo().m();
System.err.println("Test passed");
}
}
This is because the signature attribute for Local2's super class is incorrectly generated by javac as "Lfoo/Foo.1Local1;" while it should be "Lfoo/Foo$1Local1;" (a dollar instead of a dot). Eclipse's compiler correctly generates the signature. Javac for OpenJDK 7 will generate an invalid signature resulting in the following exception at runtime:
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
The bug is due to com.sun.tools.javac.jvm.ClassWriter.assembleClassSig():
...
if (outer.allparams().nonEmpty()) {
boolean rawOuter =
c.owner.kind == MTH || // either a local class
c.name == names.empty; // or anonymous
assembleClassSig(rawOuter
? types.erasure(outer)
: outer);
sigbuf.appendByte('.'); // BUG HERE
Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
sigbuf.appendName(rawOuter
? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength())
: c.name);
} else {
...
If we replace the line with "BUG HERE" with:
sigbuf.appendByte(rawOuter ? '$' : '.');
Then it works.
The same bug seems to be present in OpenJDK 8 but the code has moved to Types.java: http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/1ff9d5118aae/src/share/classes/com/sun/tools/javac/code/Types.java#l4652
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the sample Java code, run foo.Foo
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected to see "Test passed"
ACTUAL -
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
class Foo<Outer> {
void m(){
class Local1{}
class Local2 extends Local1{}
Local2.class.getTypeParameters();
}
public static void main(String[] args) {
new Foo().m();
System.err.println("Test passed");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
For some reason, if the Foo outer class does not take type parameters, the bug will not trigger at runtime.
Tested on OpenJDK 7 and seen the same bug in OpenJDK 8 source code
ADDITIONAL OS VERSION INFORMATION :
Irrelevant: this is generic code
A DESCRIPTION OF THE PROBLEM :
The following code compiles but fails to run:
class Foo<Outer> {
void m(){
class Local1{}
class Local2 extends Local1{}
Local2.class.getTypeParameters();
}
public static void main(String[] args) {
new Foo().m();
System.err.println("Test passed");
}
}
This is because the signature attribute for Local2's super class is incorrectly generated by javac as "Lfoo/Foo.1Local1;" while it should be "Lfoo/Foo$1Local1;" (a dollar instead of a dot). Eclipse's compiler correctly generates the signature. Javac for OpenJDK 7 will generate an invalid signature resulting in the following exception at runtime:
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
The bug is due to com.sun.tools.javac.jvm.ClassWriter.assembleClassSig():
...
if (outer.allparams().nonEmpty()) {
boolean rawOuter =
c.owner.kind == MTH || // either a local class
c.name == names.empty; // or anonymous
assembleClassSig(rawOuter
? types.erasure(outer)
: outer);
sigbuf.appendByte('.'); // BUG HERE
Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
sigbuf.appendName(rawOuter
? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength())
: c.name);
} else {
...
If we replace the line with "BUG HERE" with:
sigbuf.appendByte(rawOuter ? '$' : '.');
Then it works.
The same bug seems to be present in OpenJDK 8 but the code has moved to Types.java: http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/1ff9d5118aae/src/share/classes/com/sun/tools/javac/code/Types.java#l4652
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the sample Java code, run foo.Foo
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected to see "Test passed"
ACTUAL -
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.reflect.GenericSignatureFormatError
at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:126)
at sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:350)
at sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:312)
at sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:214)
at sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:158)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:52)
at sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41)
at sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74)
at sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:48)
at sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:65)
at java.lang.Class.getGenericInfo(Class.java:2360)
at java.lang.Class.getTypeParameters(Class.java:640)
at foo.Foo.m(foo.java:7)
at foo.Foo.main(foo.java:10)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
class Foo<Outer> {
void m(){
class Local1{}
class Local2 extends Local1{}
Local2.class.getTypeParameters();
}
public static void main(String[] args) {
new Foo().m();
System.err.println("Test passed");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
For some reason, if the Foo outer class does not take type parameters, the bug will not trigger at runtime.
- backported by
-
JDK-8048468 Javac generates invalid signatures for local types
- Resolved
-
JDK-8052615 Javac generates invalid signatures for local types
- Resolved
-
JDK-8044198 Javac generates invalid signatures for local types
- Closed
- relates to
-
JDK-8050472 javac could generate more accurate signatures for local classes
- Closed