Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] WeavingAdapter - how to use it?

Hi Andy!

Usually when I try to help people who do not clearly describe their problem, I tell them to share more information or just ask smarter. Thank you for not lecturing me on that (even though probably you should have) but trying instead to make educated guesses about my assumed problems and goals. Maybe I can do better this time. :-)

>>> If you add "-Xbootclasspath/p:<path_to_aspects.jar>" JVM option, then you can instrument inside the JDKs and also instrument already loaded classes.
> 
> Not sure that statement is quite correct.  You cannot just do that to
> instrument already loaded classes

Actually I do not use the command line option, I just quoted the full sentence. I am only interested in instrumenting already loaded classes. So here is my situation:

I have written a little playground application:

Eclipse project "main" (AspectJ):
  - class Application
  - interface Plugin
 - aspect ApplicationAccessorAspect
 - aspect PluginMonitorAspect

Eclipse project "plugin 1"  (Java):
  - class MyPlugin1 implements Plugin
Eclipse project "plugin 2"  (Java):
  - class MyPlugin2 implements Plugin
Eclipse project "plugin 2b"  (Java):
  - class MyPlugin2 implements Plugin

ApplicationAccessorAspect monitors calls (not executions!) to getters/setters in Application.

PluginMonitorAspect monitors executions (yes, this time) of two Plugin+ methods.

I successfully tested the whole setup with a WeavingURLClassLoader which weaves all plugins upon class-loading. Log output shows that all my intercepted calls and executions in both the main application and the plugins are triggered perfectly. I even verified that MyPlugin2 (same class & package name in two projects "2" and "2b", just slightly different log output so I can differentiate them) are loaded separately because I am creating a new WeavingURLClassLoader instance each time I load a plugin. Thus, the plugins run in isolation from one another. I have basically created mini containers.

Wonderful! Piece of cake! :-) But...

But now I was getting ambitious with my next project:

Eclipse project "plugin 3"  (AspectJ):
  - class HackyPlugin implements Plugin
  - class AspectJLTW (basically the class I quoted in my previous mail with slight changes)
  - aspect ApplicationHackerAspect

Okay, you see where I am going. I am trying to write a plugin which manipulates (advises, in AOP terms) its container's classes. For that purpose I need to be able to redefine an already loaded class. Because a plugin cannot just start a Java agent, I tried to do that manually utilising my version of AspectJLTW. Actually I want to redefine class Application, but because the loaded plugin is being advised by both PluginMonitorAspect and ApplicationAccessorAspect, plus the Application itself is also being advised by ApplicationAccessorAspect, I thought that for the first try I should rather advise another sibling class of the main project. So I added class Foo to the main project. It just has one static method returning a String, and I want to intercept its execution and manipulate the return value. (Are you still following?)

What I managed to do so far is load Foo.class from disk into a byte[] and manually weave it with ApplicationHackerAspect. The advice is triggered, so far so good. I can use before or after, but when I use around I can only do that when I skip proceed(). As soon as I call proceed() I am running into

java.lang.reflect.InvocationTargetException
(...)
Caused by: java.lang.NoSuchMethodError: de.scrum_master.aop.ltw_dynamic.Foo.getText_aroundBody0()Ljava/lang/String;
	at de.scrum_master.aop.ltw_dynamic.Foo$AjcClosure1.run(Foo.java:1)
	at com.vendor3.ApplicationHackerAspect.ajc$around$com_vendor3_ApplicationHackerAspect$1$30d0d5e4proceed(ApplicationHackerAspect.aj:8)
	at com.vendor3.ApplicationHackerAspect.ajc$around$com_vendor3_ApplicationHackerAspect$1$30d0d5e4(ApplicationHackerAspect.aj:9)
	at de.scrum_master.aop.ltw_dynamic.Foo.getText(Foo.java:4)

Somehow there seems to be a class-loading issue. Probably this is because I don't know sh** about class-loading and LTW, weaving adapters and the JDK's instrumentation interface. Furthermore, I have no idea how to manually redefine/replace the original class Foo because mi woven version exists in a separate classloader, i.e. also somehow in isolation.

Maybe I should have zipped up my Eclipse projects and attached them here, but I thought I should give it a try and explain in prose what I have accomplished and what remains to be achieved. My whole purpose is not to hack a server or anything, but to see how far I can push the limits of LTW and - foremost - to learn.

I would be glad to get any new hints about what my class-loading issue with proceed() could be (and how to solve it) and what I need to do to really replace my wonderfully woven Foo class (later maybe even the Application class) in the main application context instead of creating a clone. In Star Trek TNG speak: I want to improve Data's programming, not replace him by his evil twin Lore. ;-)

Cheers
--
Alexander Kriegisch


Back to the top