Bug 114436 - java.lang.ClassFormatError when using abstract aspect with perthis/pertarget
Summary: java.lang.ClassFormatError when using abstract aspect with perthis/pertarget
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.5.0M4   Edit
Hardware: PC Windows XP
: P2 major (vote)
Target Milestone: 1.5.0RC1   Edit
Assignee: Andrew Clement CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-10-31 17:49 EST by Ed French CLA
Modified: 2005-11-15 09:44 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed French CLA 2005-10-31 17:49:37 EST
NOTE; The following works in latest stable release (1.2.1).

Using a simple abstract aspect with perthis or pertarget scope along with a 
concrete implementation of the aspect applied to a simple class results in a 
ClassFormatError Exception (Repetitive interface name).

This can easily be duplicated using the following directory structure with the 
following files.

Directory Structure:
--------------------
make.bat
lib/
    aspectjrt.jar
src/aspects/
    abstract-test-aspect.aj
    concrete-test-aspect.aj
src/java/
    TestClass.java
target/

------------------------------------
File: abstract-test-aspect.aj
------------------------------------
abstract aspect SimpleTracing perthis(tracedCall())
{
    abstract pointcut tracedCall();

    before(): tracedCall() {
        System.out.println("Entering: " + thisJoinPoint);
    }
}

------------------------------------
File: concrete-test-aspect.aj
------------------------------------
aspect ConcreteSimpleTracing extends SimpleTracing
{
    pointcut tracedCall(): execution(void doSomething(String));
}

------------------------------------
File: TestClass.java
------------------------------------
public class TestClass
{
  public void doSomething(String stuff)
  {
    System.out.println("TestClass.doSomething(\""+stuff+"\")");
  }
  
  public static void main(String[] args)
  {
    TestClass test = new TestClass();
    test.doSomething("withThis");
  }
}

------------------------------------
File: make.bat
------------------------------------
@echo off
set CP=lib\aspectjrt.jar

:: Build the aspect library
echo Building Aspect Library...
call ajc -cp %CP% -sourceroots src/aspects -outjar target/aspects.jar

:: compile the source and apply the aspects to the results
echo Compiling classes with weaving...
call ajc -cp %CP% -sourceroots src/java -aspectpath target/aspects.jar -d 
target/classes

:: run the test
::    This results in the following Exception: java.lang.ClassFormatError: 
Repetitive interface name
::    The compiled TestClass is declared as implementing the same interface 
twice:
::        public class TestClass
::          implements ConcreteSimpleTracing.ajcMightHaveAspect, 
ConcreteSimpleTracing.ajcMightHaveAspect
::
echo Running TestClass...
set CP=%CP%;target/aspects.jar;target/classes
java -cp %CP% TestClass
------------------------------------

Running the above batch file results in the following output:

Building Aspect Library...
Compiling classes with weaving...
Running TestClass...
Exception in thread "main" java.lang.ClassFormatError: Repetitive interface 
name
 in class file TestClass
        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)


If you decompile the TestClass.class file you see the cause of the problem - 
ConcreteSimpleTracing.ajcMightHaveAspect is declared twice:

File: TestClass.class
---------------------
import java.io.PrintStream;
import org.aspectj.runtime.reflect.Factory;

public class TestClass
    implements ConcreteSimpleTracing.ajcMightHaveAspect, 
ConcreteSimpleTracing.ajcMightHaveAspect
{

    public TestClass()
    {
    }

    public void doSomething(String stuff)
    {
        String s = stuff;
        org.aspectj.lang.JoinPoint joinpoint = Factory.makeJP(ajc$tjp_0, this, 
this, s);
        ConcreteSimpleTracing.ajc$perObjectBind(this);
        if(ConcreteSimpleTracing.hasAspect(this))
            ConcreteSimpleTracing.aspectOf(this).ajc$before$SimpleTracing$1
$ce45787e(joinpoint);
        System.out.println("TestClass.doSomething(\"" + stuff + "\")");
    }

    public static void main(String args[])
    {
        TestClass test = new TestClass();
        test.doSomething("withThis");
    }

    public ConcreteSimpleTracing ajc$ConcreteSimpleTracing$perObjectGet()
    {
        return ajc$ConcreteSimpleTracing$perObjectField;
    }

    public void ajc$ConcreteSimpleTracing$perObjectSet(ConcreteSimpleTracing 
concretesimpletracing)
    {
        ajc$ConcreteSimpleTracing$perObjectField = concretesimpletracing;
    }

    public ConcreteSimpleTracing ajc$ConcreteSimpleTracing$perObjectGet()
    {
        return ajc$ConcreteSimpleTracing$perObjectField;
    }

    public void ajc$ConcreteSimpleTracing$perObjectSet(ConcreteSimpleTracing 
concretesimpletracing)
    {
        ajc$ConcreteSimpleTracing$perObjectField = concretesimpletracing;
    }

    private transient ConcreteSimpleTracing 
ajc$ConcreteSimpleTracing$perObjectField;
    private static final org.aspectj.lang.JoinPoint.StaticPart ajc$tjp_0;
    private transient ConcreteSimpleTracing 
ajc$ConcreteSimpleTracing$perObjectField;

    static 
    {
        Factory factory = new Factory("TestClass.java", Class.forName
("TestClass"));
        ajc$tjp_0 = factory.makeSJP("method-execution", factory.makeMethodSig
("1", "doSomething", "TestClass", "java.lang.String:", "stuff:", "", "void"), 

3);
    }
}
Comment 1 Adrian Colyer CLA 2005-11-03 11:11:46 EST
marked for rc1
Comment 2 Andrew Clement CLA 2005-11-14 12:16:22 EST
I've recreated this and will check in the fix tomorrow.
Comment 3 Andrew Clement CLA 2005-11-15 05:57:57 EST
fix checked in, waiting on build.  The problem was that the PerObject type
munger was being applied multiple times.  
Comment 4 Andrew Clement CLA 2005-11-15 09:44:22 EST
fix available.