Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Restricting LTW to a ClassLoader

Hi Norman,

Thanks for testing that out.  From your stack trace I can see that the
closure generated by AspectJ to handle the proceed call cannot see the
groovy script.  That is happening because the InnerLoader inside
GroovyClassLoader is defining the script but the GroovyClassLoader
itself is defining the generated closure.  They need to both we
defined by the same loader.  A solution is to build the InnerLoader
earlier and give it to AspectJ so the generated closures can also be
registered with it.  The new WeavingGroovyClassLoader is as follows:

class WeavingGroovyClassLoader extends GroovyClassLoader {

		ClassLoaderWeavingAdaptor adaptor = null;
		InnerLoader loader;
		
	    public WeavingGroovyClassLoader(ClassLoader classLoader) {
	    	super(classLoader);
	    	// Copy of the code that is normally in createCollector - so that we
	    	// have the inner loader for AspectJ to register classes against
	    	loader = (InnerLoader) AccessController.doPrivileged(new
PrivilegedAction() {
	            public Object run() {
	                return new InnerLoader(WeavingGroovyClassLoader.this);
	            }
	        });
	    	adaptor = new ClassLoaderWeavingAdaptor();
			adaptor.initialize(loader, null);
			
		}

		
		protected ClassCollector createCollector(CompilationUnit unit,
SourceUnit su) {
	        return new WeavingClassCollector(loader, unit, su);
	    }
		
		class WeavingClassCollector extends ClassCollector {
			protected WeavingClassCollector(InnerLoader arg0, CompilationUnit
arg1, SourceUnit arg2) {
				super(arg0, arg1, arg2);
			}

			protected Class createClass(byte[] code, ClassNode classNode) {
		    	try {
					code = adaptor.weaveClass(classNode.getName(), code);
				} catch (IOException e) {
					System.err.println("Weaving failed");
					e.printStackTrace();
				}
				return super.createClass(code,classNode);
			}
		}
	}

I recreated a problem similar to yours then the above changes fixed
it.  I'll update the blog article with that.

Andy

2010/1/27 Norman Elton <normelton@xxxxxxxxx>:
> Andy -
>
> Your solution is very elegant! I hadn't dealt with class collectors
> before, I can see how they could be handy for something like this. The
> code works perfect for an aspect such as this:
>
>        before() : execution(void edu.wm.test..*.run()) {
>                System.out.println("Wrap-C");
>        }
>
> But if I try to wrap around a function call:
>
>        void around() : execution(void edu.wm.test..*.run()) {
>                System.out.println("Wrap-C PRE");
>                proceed();
>                System.out.println("Wrap-C POST");
>        }
>
> I get the following output:
>
>        Wrap-C PRE
>        Exception in thread "main" java.lang.NoClassDefFoundError:
> edu/wm/test/GroovyPoint
>                at edu.wm.test.GroovyPoint$AjcClosure1.run(GroovyPoint.groovy:1)
>                at edu.wm.test.aspects.Tracer.ajc$around$edu_wm_test_aspects_Tracer$1$3691db57proceed(Tracer.aj:1)
>                at edu.wm.test.aspects.Tracer.ajc$around$edu_wm_test_aspects_Tracer$1$3691db57(Tracer.aj:6)
>                at edu.wm.test.GroovyPoint.run(GroovyPoint.groovy:1)
>                at edu.wm.test.Tester.main(Tester.java:20)
>        Caused by: java.lang.ClassNotFoundException: edu.wm.test.GroovyPoint
>                at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
>                at java.security.AccessController.doPrivileged(Native Method)
>                at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
>                at java.lang.ClassLoader.loadClass(ClassLoader.java:315)
>                at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330)
>                at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
>                at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)
>                ... 5 more
>
> The aspect is obviously getting applied, the call is getting
> intercepted, but I can't seem to proceed() back into the code. Is this
> due to the Groovy class only existing within its own ClassLoader? But
> wasn't that the case before?
>
> Thanks again for your help!
>
> Norman
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/aspectj-users
>


Back to the top