Bug 126423 - ClassFormatError - Repetitive method name/signature
Summary: ClassFormatError - Repetitive method name/signature
Status: RESOLVED INVALID
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: JDT-Core-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: needinfo
: 126424 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-02-03 17:05 EST by Charles Rich CLA
Modified: 2009-08-30 02:06 EDT (History)
2 users (show)

See Also:


Attachments
Source file for SetBeforeAct (5.08 KB, text/plain)
2006-02-03 17:08 EST, Charles Rich CLA
no flags Details
Class file with repetitive method getParameterOps (4.99 KB, application/java)
2006-02-03 17:09 EST, Charles Rich CLA
no flags Details
Source file containing parent of SetBeforeAct (74.93 KB, text/plain)
2006-02-03 17:10 EST, Charles Rich CLA
no flags Details
Class file for Act.Base (39.49 KB, application/java)
2006-02-03 17:10 EST, Charles Rich CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Charles Rich CLA 2006-02-03 17:05:59 EST
[Note bug description continued in multiple comments... Why don't you allow
attachments? ]

I got the following error, which should never be possible: 

Exception in thread "main" java.lang.ClassFormatError: Repetitive method name/signature in class file collagen/plan/SetBeforeAct
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(Unknown Source)
	at java.security.SecureClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.defineClass(Unknown Source)
	at java.net.URLClassLoader.access$100(Unknown Source)
	at java.net.URLClassLoader$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClassInternal(Unknown Source)
	at collagen.plan.Builtin.<clinit>(Builtin.java:18)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Unknown Source)
	at com.merl.util.Utils.instantiate(Utils.java:202)
	at collagen.plan.Library$Path.setUp(Library.java:315)
	at collagen.Collagen.preInit(Collagen.java:237)
	at com.merl.util.BeanComponent$Base.init(BeanComponent.java:1222)
	at com.merl.util.BeanComponent$Base.start(BeanComponent.java:1268)
	at com.merl.util.BeanComponent$Base.main(BeanComponent.java:674)
	at com.merl.util.BeanComponentApplet.main(BeanComponentApplet.java:29)
	at collagen.Collagen.main(Collagen.java:152)

I enclose the source file later below, but the entire project is much
too large.  I am just doing a normal Java project.  Note that if I use
javac from the the command line to recompile the source file, the
offending duplicate method signature for getParameterOps() goes away:

***********************************************************************

> javap collagen.plan.SetBeforeAct
Compiled from "SetBeforeAct.java"
public class collagen.plan.SetBeforeAct extends collagen.plan.Act$Base implements collagen.plan.Manipulation,collagen.plan.SetBefore{
    public static int INDEX;
    public static final collagen.infer.equal.Term$Slot[] PARAMETERS;
    static {};
    public collagen.plan.Momento getBefore();
    public collagen.plan.Momento getAfter();
    public void setBefore(collagen.plan.Momento);
    public void setAfter(collagen.plan.Momento);
    public collagen.plan.Act$Occurrence newOccurrence(long);
    public collagen.plan.Act$Quoted getPurpose();
    public int getIndex();
    public collagen.infer.equal.Term$Slot[] getParameterOps();
    protected collagen.infer.equal.Term[] getParameterArray();
    protected void setParameterArray(collagen.infer.equal.Term[]);
    public boolean isShowable();
    public collagen.plan.SetBeforeAct();
    public collagen.plan.SetBeforeAct(collagen.plan.Actor, collagen.plan.Act$Quoted);
    public collagen.plan.SetBeforeAct(collagen.infer.equal.Term[], collagen.infer.equal.Term[], collagen.infer.equal.Term[]);
    public collagen.plan.SetBeforeAct(collagen.plan.Actor, collagen.plan.Act);
    public boolean requiresExplanation();
    public collagen.infer.tms.Proposition[] matches(collagen.infer.equal.Term, boolean);
    public java.lang.Boolean isApplicable();
    public java.lang.Boolean isAchieved();
    public collagen.infer.equal.Term$Slot[] getResultOps();  <<<ALSO WRONG!
    public collagen.infer.equal.Term$Slot[] getPropertyOps(); <<<ALSO WRONG!
    public collagen.infer.equal.Term$Slot[] getParameterOps();  <<<DUPLICATE!!!
}

****************************************************************
> javac SetBeforeAct.java
> javap collagen.plan.SetBeforeAct
Compiled from "SetBeforeAct.java"
public class collagen.plan.SetBeforeAct extends collagen.plan.Act$Base implements collagen.plan.Manipulation,collagen.plan.SetBefore{
    public static int INDEX;
    public static final collagen.infer.equal.Term$Slot[] PARAMETERS;
    public collagen.plan.Momento getBefore();
    public collagen.plan.Momento getAfter();
    public void setBefore(collagen.plan.Momento);
    public void setAfter(collagen.plan.Momento);
    public collagen.plan.Act$Occurrence newOccurrence(long);
    public collagen.plan.Act$Quoted getPurpose();
    public int getIndex();
    public collagen.infer.equal.Term$Slot[] getParameterOps();
    protected collagen.infer.equal.Term[] getParameterArray();
    protected void setParameterArray(collagen.infer.equal.Term[]);
    public boolean isShowable();
    public collagen.plan.SetBeforeAct();
    public collagen.plan.SetBeforeAct(collagen.plan.Actor, collagen.plan.Act$Quoted);
    public collagen.plan.SetBeforeAct(collagen.infer.equal.Term[], collagen.infer.equal.Term[], collagen.infer.equal.Term[]);
    public collagen.plan.SetBeforeAct(collagen.plan.Actor, collagen.plan.Act);
    public boolean requiresExplanation();
    public collagen.infer.tms.Proposition[] matches(collagen.infer.equal.Term, boolean);
    public java.lang.Boolean isApplicable();
    public java.lang.Boolean isAchieved();
    static {};
}

> Notice that not only redundant getParameterOps() goes away, but also
getPropertyOps() and getResultOps(), which are also _wrong_ (see
next comment)
Comment 1 Charles Rich CLA 2006-02-03 17:08:14 EST
Created attachment 34129 [details]
Source file for SetBeforeAct
Comment 2 Charles Rich CLA 2006-02-03 17:09:19 EST
Created attachment 34130 [details]
Class file with repetitive method getParameterOps
Comment 3 Charles Rich CLA 2006-02-03 17:10:11 EST
Created attachment 34131 [details]
Source file containing parent of SetBeforeAct
Comment 4 Charles Rich CLA 2006-02-03 17:10:34 EST
Created attachment 34132 [details]
Class file for Act.Base
Comment 5 Charles Rich CLA 2006-02-03 17:17:30 EST
Ok, the attachment option doesn't show up until the next window... 

Anyways, I attached both source file for both the offending class and its
parent, and the bad class file, and the class file for it's parent, so you can
do a full decompile to see more info.

Here's the key info re the bad method entries (you can see the last one just
leads to an infinite loop!).

I am hosed.  A workaround idea would be welcome... -CR


public collagen.infer.equal.Term$Slot[] getResultOps();
  Code:
   0:   aload_0
   1:   invokevirtual   #198; //Method
collagen/plan/Act$Base.getResultOps:()[Lcollagen/infer/equal/Term$Slot;
   4:   areturn

public collagen.infer.equal.Term$Slot[] getPropertyOps();
  Code:
   0:   aload_0
   1:   invokevirtual   #203; //Method
collagen/plan/Act_Builtin.getPropertyOps:()[Lcollagen/infer/equal/Term$Slot;
   4:   areturn

public collagen.infer.equal.Term$Slot[] getParameterOps();
  Code:
   0:   aload_0
   1:   invokevirtual   #205; //Method
getParameterOps:()[Lcollagen/infer/equal/Term$Slot;
   4:   areturn

}
Comment 6 Charles Rich CLA 2006-02-03 17:18:12 EST
*** Bug 126424 has been marked as a duplicate of this bug. ***
Comment 7 Charles Rich CLA 2006-02-03 17:26:59 EST
**********NB*************

I am using 3.1.2 (not in drop-down list above).

I am going to try falling back to 3.1.1...
(a lot of stuff happened in the meanwhile)
Comment 8 Charles Rich CLA 2006-02-03 17:43:08 EST
Dropping back to 3.1.1 didn't help.

Btw, during building I get messages like:

(100 Errors, 0 Warnings.  Fixed 53 + 0 )

Eventually there are no errors at the end.  I assume that what Eclipse is fixing is undefined types due to circularity in my class paths (between projects), which I have.  It isn't actually editing the byte codes, is it?

Maybe this is a Sun compiler error... I'll look there next...

Help!!  -CR
Comment 9 Charles Rich CLA 2006-02-03 17:56:05 EST
Falling back to 3.1.1 did not help.

I am already using the latest JDK 5.0 Update 6.

Errggggg....
Comment 10 Olivier Thomann CLA 2006-02-03 20:34:00 EST
It would be really nice if we could get a complete test case.
Even if the resulting project is pretty big, we should set up a way to retrieve it. Without a complete test case, it is difficult to reproduce this issue.
Thanks.
Comment 11 Charles Rich CLA 2006-02-03 22:09:26 EST
Hi Olivier,  Thanks for responding so quickly.

I hear you about a reproducible test case, but I am afraid it would be very difficult for me to post the whole project, in part because it is proprietary code.  

I was hoping that someone who knows the insides of the compiler would have a clue from the particular symptom of generating extraneous methods.  Basically the compiler should obviously _never_ produce such broken byte code.

Another thing I wonder about is why use javac gives the correct result:  Eclipse uses the compiler code from the JDK, doesn't it?  If so, all I can figure out is that the _order_ of compilation in the Eclipse build process somehow triggers a latent Sun compiler bug; or perhaps Eclipse _uses_ the compiler in some special optimized way?

Btw, I checked on the Sun web site for bugs related to this ClassFormatError, but didn't see any.

Any help would be appreciated, especially from a compiler expert.

Thanks, -CR
Comment 12 Charles Rich CLA 2006-02-04 15:07:10 EST
Ok, I see that Eclipse really does have is own compiler, distinct from the Sun compiler... So this really is a bug in the Eclipse compiler...  

Any compiler experts out there who might suggest a workaround? 

Has anything like this been fixed in the 3.2.2 release?  (I looked through the build notes and saw lots of bugs fixed in the compiler...).

Thanks in advance, -CR
Comment 13 Philipe Mulet CLA 2006-02-04 16:42:23 EST
Charles,

Without steps to reproduce, it is hard to figure what is going on. Basically, your samples to do not compile out of their context, and it would be tedious to infer anything from these fragments. The theory is that duplicates should never occur, and compiler checks before adding synthetics/bridge methods for collisions with user code. Now you may have found a bug in this area.

We haven't made any fix in this area, neither have heard of a similar problem to date.
Comment 14 Olivier Thomann CLA 2006-02-05 20:09:18 EST
I would really encourage you to extract a test case that would provide all necessary classes. So if you could provide all the classes to compile the source file SetBeforeAct.java, this would greatly help.
You can strip the method body of the dependant classes if you don't want to provide the code.
Comment 15 Charles Rich CLA 2006-02-05 21:19:37 EST
[Sorry this posting is a bit long, but I think it is worthwhile... -CR]

Cher Olivier et Philippe,

First let me sincerely apologize for not being able to provide you with a reproducible test---I understand completely why you are reluctant to look at this bug without one; and Eclipse is after all a community effort.

On the other hand, I figured out some more information over the weekend (I spent a fair bit of it on this problem), which I think should be able to lead you to the buggy code in the compiler, so that this doesn't happen to anyone else.

The clue is that (as I mentioned in my original posting) there are circular project dependencies in my class path.  Indeed, the compiler does warn me about this, but I think producing an illegal class file is a bit of an extreme reacion on its part :-).  When I divided one of my projects into two parts to avoid the circularity, the problem disappeared!  Also, all the messages in the progress windows about "Fixing" errors no longer appears.

Coming back to the issue of duplicate methods, it seems to me that this is a fairly simple invariant to verify by code inspection.  All you need to do is to make sure that every place a method signature (synthetic or not) is added, there is an unavoidable check for duplicates.  There can't be that many places where methods are added, and if there are a lot, they should/could all go through a shared utility method which checks for duplicates.  

Furthermore, given the circularity issue above, my guess is that there is some clever editing of class files going on, e.g., first a "placeholder" method is added, and then on the next compilation cycle of the circularity, it is supposed to be updated with the "real" method, but the code accidentally forgets to delete the synthetic method.  

In any case, there definitely is a (bad) bug, and I think that a careful code inspection, informed by the information provided here, is likely to find it.

I will curious to hear what happens,

Bon chance!  -CR

Comment 16 Philipe Mulet CLA 2006-02-10 12:46:08 EST
Merci (thanks) Charles.
The theory is that all such field/method creations are already protected.
Comment 17 Philipe Mulet CLA 2006-02-10 13:16:17 EST
Also, can you reproduce this issue in latest 3.2 integration build ?
Comment 18 Charles Rich CLA 2006-02-10 13:20:22 EST
Philippe,

 > The theory is that all such field/method creations are already protected.

We agree that is the theory, but the practice appears to be different :-).  Seriously, though, my experience in similar cases is that a careful code walkthrough to verify the theory (especially when one has strong reason to believe there is a hole) often finds the hole.  It's up to you.

 > Also, can you reproduce this issue in latest 3.2 integration build ?

Sorry, but I am loathe to reconfigure my projects back to their losing configuration, now that I have things working again.

-CR
Comment 19 Olivier Thomann CLA 2006-04-20 11:17:42 EDT
Charles,

Are you using compliance 1.3 in your compiler settings ?
Please check bug 137744.
Comment 20 Charles Rich CLA 2006-04-21 14:21:59 EDT
To Olivier:

I am using compliance 5.0.

Bug 1377744 certainly does look related.  Perhaps it was not totally fixed in 1.3 and is showing up in a slightly different form here?
Comment 21 Olivier Thomann CLA 2006-04-21 14:25:08 EDT
Let us know if you can reproduce using a build > 20060421.
Comment 22 Philipe Mulet CLA 2006-04-21 15:28:52 EDT
Bug 137744 relates to a regression introduced with perf work for sorting method bindings. The present bug was discovered prior to introduction of sorting, which is also confirmed by the fact it also occurs on 3.1.1.

I am suspecting a bogus addition of a bridge method or something like this.

Kent - did you fix some bridge issues lately ?
Comment 23 Kent Johnson CLA 2006-04-21 15:34:42 EDT
yes - see bug 132831
Comment 24 Philipe Mulet CLA 2006-04-25 10:45:53 EDT
Pls reopen if symptoms persist in latest.
Comment 25 Denis Roy CLA 2009-08-30 02:06:06 EDT
As of now 'LATER' and 'REMIND' resolutions are no longer supported.
Please reopen this bug if it is still valid for you.