Bug 182836 - [itds] [ltw] Duplicate ITD Members with Load-Time Weaving Depending on Load Order
Summary: [itds] [ltw] Duplicate ITD Members with Load-Time Weaving Depending on Load O...
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: LTWeaving (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-04-17 18:03 EDT by Ron Bodkin CLA
Modified: 2013-06-24 11:05 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ron Bodkin CLA 2007-04-17 18:03:00 EDT
AspectJ load-time weaving can add a duplicate copy of ITD's if an ITD affects a base class and a derived class and the derived class is loaded first. This may only affect storage space and programs that use reflection (in a few basic tests, the semantics of the ITDs look ok). Consider the difference between running the following program using Sample as the main class or Derived (in the latter case you get the extra ITD, although the counter is behaving in a similar way: the ITD field on the superclass is just not being used). It would be better to not have this extra state and I'm also nervous that subtle semantics bugs lurk here.

public class Sample implements SubMarker {

    public void print() {
        for (Class clazz = getClass(); clazz!=null; clazz=clazz.getSuperclass()) {
            System.out.print("Fields for "+clazz.getName()+":");
            for (java.lang.reflect.Field f : clazz.getDeclaredFields()) {
                System.out.print(" "+f.getName()+"=");
                f.setAccessible(true);
                try {
                    System.out.print(f.get(this));
                } catch (Exception e) {
                    throw new RuntimeException("failure",e);
                }
            }
            System.out.println();
        }
    }

    public static void main(String args[]) {
        test(new Derived());
        test(new Sample());
    }
    
    private static void test(Sample b) {
        System.out.println("Testing "+b.getClass().getName());
        b.foo();
        b.print();
        
        b.bar();
    }
    
    public void foo() {}

    public void bar() {}
}

interface Marker {}

interface SubMarker extends Marker {}

public class Derived extends Sample implements Marker {
    public void foo() {
        super.foo();
    }
}

public aspect ItdOnMarker {
    private static interface Holder {} 
    declare parents: Marker+ && !Holder+ implements Holder;
    public int Holder.x;
    
    before(Holder holder) : execution(public * Holder+.*(..)) && this(holder) {
        System.out.print(thisJoinPoint+" "+ (++holder.x));
        if (holder instanceof Marker) {
            System.out.print(" & m: "+((Marker)holder).x);
        }
        System.out.println();
    }
}

ajc -5.0 -outjar sample.jar Sample.java Derived.java


ajc -classpath sample.jar;%CLASSPATH% -outjar itd.jar -outxml ItdOnMarker.aj

C:\devel\glassbox\test>java -javaagent:\devel\aspectj\dev\20070129\lib\aspectjwe
aver.jar -classpath sample.jar;itd.jar;%CLASSPATH% Derived
Testing Derived
execution(void Derived.foo()) 1 & m: 1
execution(void Sample.foo()) 2 & m: 2
execution(void Sample.print()) 3 & m: 3
Fields for Derived: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=3 ajc$tjp_0=
execution(void Derived.foo())
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=0 ajc$tjp_0=e
xecution(void Sample.print()) ajc$tjp_1=execution(void Sample.foo()) ajc$tjp_2=e
xecution(void Sample.bar())
Fields for java.lang.Object:
execution(void Sample.bar()) 4 & m: 4
Testing Sample
execution(void Sample.foo()) 1 & m: 1
execution(void Sample.print()) 2 & m: 2
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=2 ajc$tjp_0=e
xecution(void Sample.print()) ajc$tjp_1=execution(void Sample.foo()) ajc$tjp_2=e
xecution(void Sample.bar())
Fields for java.lang.Object:
execution(void Sample.bar()) 3 & m: 3

C:\devel\glassbox\test>java -javaagent:\devel\aspectj\dev\20070129\lib\aspectjwe
aver.jar -classpath sample.jar;itd.jar;%CLASSPATH% Sample
Testing Derived
execution(void Derived.foo()) 1 & m: 1
execution(void Sample.foo()) 2 & m: 2
execution(void Sample.print()) 3 & m: 3
Fields for Derived: ajc$tjp_0=execution(void Derived.foo())
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=3 ajc$tjp_0=e
xecution(void Sample.print()) ajc$tjp_1=execution(void Sample.foo()) ajc$tjp_2=e
xecution(void Sample.bar())
Fields for java.lang.Object:
execution(void Sample.bar()) 4 & m: 4
Testing Sample
execution(void Sample.foo()) 1 & m: 1
execution(void Sample.print()) 2 & m: 2
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=2 ajc$tjp_0=e
xecution(void Sample.print()) ajc$tjp_1=execution(void Sample.foo()) ajc$tjp_2=e
xecution(void Sample.bar())
Fields for java.lang.Object:
execution(void Sample.bar()) 3 & m: 3
Comment 1 Andrew Clement CLA 2008-10-02 14:15:53 EDT
raised a while ago, need to determine what the current state of things here is before proceeding
Comment 2 Andrew Clement CLA 2009-02-12 13:21:33 EST
Having a bit of trouble understanding that output.  But basically it seems when I compare the output when the bug was raised, if you run Sample:

Fields for Derived: ajc$tjp_0=execution(void Derived.foo())
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=3

And if you run Derived:
Fields for Derived: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=3
ajc$tjp_0=execution(void Derived.foo())
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x=0

So when running the subtype there are two fields called x.

This appears to still happen with AspectJ 1.6.4.  Although I'm trimming down the testcase to show the actual problem more clearly... ok, now it is more clear, ignore extraneous jp messages and ajc$tjp fields:

F:\workspaces\aspectj16_1\AA\src>java -javaagent:f:\aspectj164-dev\lib\aspectjweaver.jar -classpath "sample.jar;itd.jar;%CLASSPATH%" Derived
Testing Derived
Fields for Derived: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Testing Sample
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x

F:\workspaces\aspectj16_1\AA\src>java -javaagent:f:\aspectj164-dev\lib\aspectjweaver.jar -classpath "sample.jar;itd.jar;%CLASSPATH%" Sample
Testing Derived
Fields for Derived:
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Testing Sample
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x

In the case of launching Derived first, it gets the ITD field, as does Sample, the top most implementor.  Now try with ltw debugging
Comment 3 Andrew Clement CLA 2009-02-12 14:04:54 EST
ok, I've turned on showWeaveInfo and verbose mode in aop.xml

Running Derived:
info AspectJ Weaver Version DEVELOPMENT built on Monday Feb 9, 2009 at 19:43:46 GMT
info register classloader sun.misc.Launcher$AppClassLoader@1f12c4e
info using configuration file:/F:/workspaces/aspectj16_1/AA/src/itd.jar!/META-INF/aop-ajc.xml
info using configuration /F:/workspaces/aspectj16_1/AA/src/META-INF/aop-ajc.xml
info register aspect ItdOnMarker
info register aspect ItdOnMarker
weaveinfo Extending interface set for type 'Derived' (Derived.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Type 'Derived' (Derived.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Join point 'method-execution(void Derived.foo())' in Type 'Derived' (Derived.java:2) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Extending interface set for type 'Marker' (Marker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
info processing reweavable type ItdOnMarker$Holder: \ItdOnMarker.java
info successfully verified type ItdOnMarker exists.  Originates from F:\workspaces\aspectj16_1\AA\src\ItdOnMarker.java
weaveinfo Type 'ItdOnMarker$Holder' (ItdOnMarker.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Type 'Sample' (Sample.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Join point 'method-execution(void Sample.print())' in Type 'Sample' (Sample.java:3) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Join point 'method-execution(void Sample.foo())' in Type 'Sample' (Sample.java:28) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Join point 'method-execution(void Sample.bar())' in Type 'Sample' (Sample.java:31) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
info processing reweavable type ItdOnMarker: \ItdOnMarker.java

Testing Derived
Fields for Derived: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Testing Sample
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x


Running Sample:
info AspectJ Weaver Version DEVELOPMENT built on Monday Feb 9, 2009 at 19:43:46 GMT
info register classloader sun.misc.Launcher$AppClassLoader@1f12c4e
info using configuration file:/F:/workspaces/aspectj16_1/AA/src/itd.jar!/META-INF/aop-ajc.xml
info using configuration /F:/workspaces/aspectj16_1/AA/src/META-INF/aop-ajc.xml
info register aspect ItdOnMarker
info register aspect ItdOnMarker
weaveinfo Extending interface set for type 'Sample' (Sample.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Type 'Sample' (Sample.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Join point 'method-execution(void Sample.print())' in Type 'Sample' (Sample.java:3) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Join point 'method-execution(void Sample.foo())' in Type 'Sample' (Sample.java:28) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Join point 'method-execution(void Sample.bar())' in Type 'Sample' (Sample.java:31) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
weaveinfo Extending interface set for type 'SubMarker' (SubMarker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Extending interface set for type 'Marker' (Marker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
info processing reweavable type ItdOnMarker$Holder: \ItdOnMarker.java
info successfully verified type ItdOnMarker exists.  Originates from F:\workspaces\aspectj16_1\AA\src\ItdOnMarker.java
weaveinfo Type 'ItdOnMarker$Holder' (ItdOnMarker.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Join point 'method-execution(void Derived.foo())' in Type 'Derived' (Derived.java:2) advised by before advice from 'ItdOnMarker' (ItdOnMarker.java:7)
info processing reweavable type ItdOnMarker: \ItdOnMarker.java

Testing Derived
Fields for Derived:
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x
Testing Sample
Fields for Sample: ajc$interField$ItdOnMarker$ItdOnMarker$Holder$x

Here is is reduced down:

Running Derived
info register aspect ItdOnMarker
weaveinfo Extending interface set for type 'Derived' (Derived.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Type 'Derived' (Derived.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Extending interface set for type 'Marker' (Marker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
info processing reweavable type ItdOnMarker$Holder: \ItdOnMarker.java
weaveinfo Type 'ItdOnMarker$Holder' (ItdOnMarker.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Type 'Sample' (Sample.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
info processing reweavable type ItdOnMarker: \ItdOnMarker.java

Running Sample
info register aspect ItdOnMarker
weaveinfo Extending interface set for type 'Sample' (Sample.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Type 'Sample' (Sample.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
weaveinfo Extending interface set for type 'SubMarker' (SubMarker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
weaveinfo Extending interface set for type 'Marker' (Marker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)
info processing reweavable type ItdOnMarker$Holder: \ItdOnMarker.java
weaveinfo Type 'ItdOnMarker$Holder' (ItdOnMarker.java) has intertyped field from 'ItdOnMarker' (ItdOnMarker.java:'int ItdOnMarker$Holder.x')
info processing reweavable type ItdOnMarker: \ItdOnMarker.java

it looks like the existence of the Marker interfaces is also interfering as this message:

weaveinfo Extending interface set for type 'SubMarker' (SubMarker.java) to include 'ItdOnMarker$Holder' (ItdOnMarker.java)

doesn't come out when running Derived
Comment 4 Andrew Clement CLA 2013-06-24 11:05:16 EDT
unsetting the target field which is currently set for something already released