Community
Participate
Working Groups
When reading annotations from a package, the following error is thrown: Exception in thread "main" java.lang.ClassFormatError: Illegal class modifiers in class testcase/package-info: 0x1600 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:242) at java.lang.Package.getPackageInfo(Package.java:350) at java.lang.Package.getAnnotation(Package.java:361) at testcase.Main.main(Main.java:9) This only happens when eclipse (3.1m6) compiles package-info.java; if I use javac to compile it, reading package annotations works fine.
Created attachment 19976 [details] Test case for failure Testcase for the bug. Create an eclipse project, compile these sources, and run Main.
I have some more info on the problem. IDEA can compile package-info fine, so I compared the class files generated by both. Here is class file #1 (generated by Eclipse): Compiled from "package-info.java" interface com.rbc.uk.proj.cobra.package-info SourceFile: "package-info.java" RuntimeVisibleAnnotations: length = 0x10 00 01 00 08 00 02 00 09 73 00 0A 00 0B 73 00 0C minor version: 0 major version: 49 Constant pool: const #1 = Asciz com/foo/package-info; const #2 = class #1; // "com/foo/package-info" const #3 = Asciz java/lang/Object; const #4 = class #3; // java/lang/Object const #5 = Asciz SourceFile; const #6 = Asciz package-info.java; const #7 = Asciz RuntimeVisibleAnnotations; const #8 = Asciz Ljavax/persistence/SequenceGenerator;; const #9 = Asciz name; const #10 = Asciz SEQ_GEN; const #11 = Asciz sequenceName; const #12 = Asciz SQ_CDB_IDS; { } And here is class file #2 (generated by IDEA): Compiled from "package-info.java" interface com.rbc.uk.proj.cobra.package-info SourceFile: "package-info.java" RuntimeVisibleAnnotations: length = 0x10 00 01 00 06 00 02 00 07 73 00 08 00 09 73 00 0A minor version: 0 major version: 49 Constant pool: const #1 = class #11; // "com/foo/package-info" const #2 = class #12; // java/lang/Object const #3 = Asciz SourceFile; const #4 = Asciz package-info.java; const #5 = Asciz RuntimeVisibleAnnotations; const #6 = Asciz Ljavax/persistence/SequenceGenerator;; const #7 = Asciz name; const #8 = Asciz SEQ_GEN; const #9 = Asciz sequenceName; const #10 = Asciz SQ_CDB_IDS; const #11 = Asciz com/foo/package-info; const #12 = Asciz java/lang/Object; { } The constant pool layouts are different. This may not be the problem - the issue could be in one of the fields defined after the constant pool layout. I have been looking at http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#80959 for a comparison, but time is tight, so I will have to leave it for now.
Did you try with M7?
Reproduced in M7. I am investigating.
The problem comes from the fact that the synthetic bit was set. I removed it. Fixed and released in HEAD. Regression test added in org.eclipse.jdt.core.tests.builder.PackageInfoTest.test002
Thanks Oliver. I did eventually manage to trace it back to the access flags in the class file, which were 0x1600 in the class file generated by Eclipse, which I presume is a result of ORing ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC where the synthetic flag was erroneous. I presume that the correct value should be 0x0600 then? If this is the case, this is also slightly confusing, as IDEA's class files (which also work) have an access_flags field of 0x0200, which is ACC_INTERFACE. It says in the class file format ref that if ACC_INTERFACE is set, ACC_ABSTRACT should also be set, so unless I'm missing something, this should also be invalid?
I think you are right. We did set the synthetic bit because we considered this fake interface has no corresponding source and is purely generated by the compiler. From my understanding of what synthetic means this should be set as synthetic. It seems that Sun is considering tagging it as synthetic in the future. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6232928 The VM spec say: If the ACC_INTERFACE flag of this class file is set, its ACC_ABSTRACT flag must also be set (§2.13.1) and its ACC_PUBLIC flag may be set. Such a class file must not have any of the other flags in Table 4.1 set. then the other class file should be invalid. Anyway, I removed the synthetic bit to workaround this VM bug.
Verified for 3.1 RC1 with build I20050527-0010.