Bug 270874 - ClassLoaderWeavingAdaptor tries to reweave compiled aspectj, logs warning
Summary: ClassLoaderWeavingAdaptor tries to reweave compiled aspectj, logs warning
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: LTWeaving (show other bugs)
Version: 1.6.3   Edit
Hardware: Macintosh Mac OS X - Carbon (unsup.)
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-04-01 16:29 EDT by Saxon D'Aubin CLA
Modified: 2009-04-30 16:45 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 Saxon D'Aubin CLA 2009-04-01 16:29:38 EDT
I'm trying to get past a LinkageError logged at warning level during runtime weaving.  I'm using AspectJ1.6.3, but the same problem occurs in 1.5.  

I'm trying to compile the Glassbox source with the source & target set to 1.5.  The aspects in the source are compiled, but weaving is used to hook into non-Glassbox classes at runtime and record invocation metrics.  When the source is set to 1.4, all of the glassbox code is ignored in the runtime weave (it's listed in the aop excludes).  When the source is set to 1.5, the compiled classes contain annotations, and even though their packages are listed in the excludes, the weaving classloader notices the annotations and tries to reweave them.  If I could just make the weaving classloader ignore my classes I'd be in good shape, but the behavior of the classloader is different when the source level is changed from 1.4 to 1.5.

The compilation step of my build creates an inner ajcMightHaveAspect class.  When I start my app, the weaving classloader tries to create this class again, a LinkageError is thrown, caught, and logged at warn level.  

Here's the aspectj code:

/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptor.java (line 799 is the logging)

		try {
			// TODO av protection domain, and optimize
			Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", new Class[] { String.class, bytes.getClass(),
					int.class, int.class });
			defineClass.setAccessible(true);
			clazz = defineClass.invoke(loader, new Object[] { name, bytes, new Integer(0), new Integer(bytes.length) });
		} catch (InvocationTargetException e) {
			if (e.getTargetException() instanceof LinkageError) {
				warn("define generated class failed", e.getTargetException());
				// is already defined (happens for X$ajcMightHaveAspect interfaces since aspects are reweaved)
				// TODO maw I don't think this is OK and
			} else {
				warn("define generated class failed", e.getTargetException());
			}

I want to know how to avoid this warning.  Logging an exception at this level is not acceptable.  Is there any way to compile my aspects to avoid this error?  Is there some hint that can be added to the annotations?  

The comment "maw I don't think this is OK" makes it sound like you guys planned to revisit how this case is handled.  If there is no way to work around this problem, could you guys at least lower the log level of this statement?

Here's a sample of my code:

  @Aspect("perthis(within(AbstractMonitorClass+) && execution(new(..)))")
    public class RuntimeControl {
    }
Comment 1 Andrew Clement CLA 2009-04-29 13:35:42 EDT
> When the source is set to 1.5, the compiled classes contain annotations, 
> and even though their packages are listed in the excludes, the weaving 
> classloader notices the annotations and tries to reweave them.  If I 
> could just make the weaving classloader ignore my classes I'd be in
> good shape, but the behavior of the classloader is different when the 
> source level is changed from 1.4 to 1.5.

I worry about this, I don't understand why the annotations are triggering weaving if the classes are set to be ignored.  Can we try and work towards a testcase?  Here is what I have:

--- Test.java ---
@Foo
public class Test {
  public static void main(String[] argv) {
    new B().run();
  }
}

@Foo
class B {
  void run() {}
}

aspect X {
  before(): execution(* *(..)) && @within(Foo) {
    System.out.println("Advised "+thisJoinPoint);
  }
}

@interface Foo {
}
-----------------

ajc -1.5 Test.java
java Test

Advised execution(void Test.main(String[]))
Advised execution(void B.run())

both advised.  So I add:
--- META-INF/aop.xml ---
<aspectj>
  <aspects>
    <aspect name="X"/>
  </aspects>
  <weaver options="-debug">
    <exclude within="Test"/>
  </weaver>
</aspectj>
------------------------

which says I don't want to weave Test.

java -javaagent:lib\aspectjweaver.jar Test
[AppClassLoader@1f12c4e] debug not weaving 'Test'
[AppClassLoader@1f12c4e] debug cannot weave 'org.aspectj.lang.Signature'
... skip lots of messages about other org.aspectj types ...
[AppClassLoader@1f12c4e] debug weaving 'X'
... skip lots of messages about other org.aspectj types ...
Advised execution(void Test.main(String[]))
[AppClassLoader@1f12c4e] debug weaving 'B'
Advised execution(void B.run())

We can see that Test was not woven (but happened to still be woven from the compile time weave).

What does your aop xml file say?  Does the -debug output from the ltw show it is weaving things you did not expect it to?