Community
Participate
Working Groups
I am getting the following stacktrace, when starting class test.Test.main: java.lang.ClassFormatError: test/B (Repetitive method name/signature) at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:539) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123) at java.net.URLClassLoader.defineClass(URLClassLoader.java:251) at java.net.URLClassLoader.access$100(URLClassLoader.java:55) at java.net.URLClassLoader$1.run(URLClassLoader.java:194) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:187) at java.lang.ClassLoader.loadClass(ClassLoader.java:289) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274) at java.lang.ClassLoader.loadClass(ClassLoader.java:235) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302) Exception in thread "main" I have attached a test case. The decompiled class B using jad looks like this: package test; // Referenced classes of package test: // A, IA3, IA1 public abstract class B extends A implements IA3, IA1 { public B() { } public void test() { } public abstract boolean hasKursAt(int i); public abstract boolean hasKursAt(int i); int a; } The problem arises because of severel interfaces containing the same method: public abstract boolean hasKursAt(int i); I was not able to reduce the test case any further. I am using jdk 1.4.2_08 as runtime. This bug may be a duplicate: https://bugs.eclipse.org/bugs/show_bug.cgi?id=126423
Created attachment 39037 [details] The test case.
I'll investigate it.
I used Eclipse 3.2 RC 1. We had no problems using 3.1.*
I tried your test case and it doesn't fail. What VM are you using? Could you please provide your compiler settings ? Thanks.
Some more info: we use the following Java Compiler Preferences: Compiler Compliance Level: 1.3 Generated Class Files compatibility: 1.1 Source Compatibility: 1.3 The problem vanished if I set all to 1.4.
This certainly reduces the severity to minor. We are using sun jdk 1.4.2_08.
Reproduced if the compiler compliance is set to 1.3. Thanks for the steps.
If the compliance is 1.3, B.class looks like this: // Compiled from B.java (version 1.1 : 45.3, super bit) public abstract class test.B extends test.A implements test.IA3, test.IA1 { Constant pool: constant #1 class: #2 test/B constant #2 utf8: "test/B" constant #3 class: #4 test/A constant #4 utf8: "test/A" constant #5 class: #6 test/IA3 constant #6 utf8: "test/IA3" constant #7 class: #8 test/IA1 constant #8 utf8: "test/IA1" constant #9 utf8: "a" constant #10 utf8: "I" constant #11 utf8: "<init>" constant #12 utf8: "()V" constant #13 utf8: "Code" constant #14 method_ref: #3.#15 test/A.<init> ()V constant #15 name_and_type: #11.#12 <init> ()V constant #16 utf8: "LineNumberTable" constant #17 utf8: "LocalVariableTable" constant #18 utf8: "this" constant #19 utf8: "Ltest/B;" constant #20 utf8: "test" constant #21 utf8: "hasKursAt" constant #22 utf8: "(I)Z" constant #23 utf8: "SourceFile" constant #24 utf8: "B.java" // Field descriptor #10 I int a; // Method descriptor #12 ()V // Stack: 1, Locals: 1 public B(); 0 aload_0 [this] 1 invokespecial test.A() [14] 4 return Line numbers: [pc: 0, line: 13] [pc: 4, line: 14] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: test.B // Method descriptor #12 ()V // Stack: 0, Locals: 1 public void test(); 0 return Line numbers: [pc: 0, line: 17] Local variable table: [pc: 0, pc: 1] local: this index: 0 type: test.B // Method descriptor #22 (I)Z public abstract boolean hasKursAt(int arg0); // Method descriptor #22 (I)Z public abstract boolean hasKursAt(int arg0); } We do have a duplicate method in it.
The bug seems to come from the fact that the methods are not sorted once the default abstract method is added. Then the call implementsMethod(method) might returns false even if the method is already in the list.
Created attachment 39041 [details] Proposed fix
There might be a more efficient way to sort the method after the addition of a default abstract method.
Thanks Olivier, that was very fast!
Created attachment 39047 [details] Better patch Might be a better patch.
Created attachment 39058 [details] New patch No need to use a temp local to store the new array. Also factorize the this.methods.length calls.
Created attachment 39059 [details] Regression test
In fact -target 1.1 is enough to reproduce the failure. When target >= 1.2, there is no longer the addition of default abstract methods. Compliance 1.3 sets the target to 1.1 by default.
All tests passed with the latest patch. Another solution would be to change isImplements(...) implementation to get rid of the assumption that the method bindings are sorted. Then only one sort would be done at the end of the method that adds all default abstract methods followed by the line: this.tagBits |= TagBits.AreMethodsSorted;
Additions of default abstracts along the checking process are definitely breaking the algorithm which relies on sorting. Will rather separate default abstracts from the method array, and only inject them at the end. This avoids multiple sorts, and multiple array growing.
Moved the regression test to LookupTest#test064.
Created attachment 39155 [details] Final patch
Fix released
*** Bug 138428 has been marked as a duplicate of this bug. ***
Verified with I20060427-1600 for 3.2RC2