[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[news.eclipse.technology.equinox] Re: AspectJ-enabled runtime implementation

Hi Chris,

This is very intruiging work.

Thanks!



What did you use to do the actual bytecode transformation?

I use the bytecode weaving implementation that is part of the current version of AspectJ 1.1 compiler. Therefore I didn't realized any kind of bytecode modification myself, I just adopted the one from the AspectJ project (Erik Hilsdale did most of implementation work for the AspectJ 1.1 bytecode weaving, I think). They are using Apache BCEL.



       public byte[] transformBytecode (Resource classResource, String
pluginId);
       }

I am somewhat concerned about performance. I just got my own project working
to instrument all plugins and visualize eclipse behavior for
educational/debugging
purposes. You may call it Aspect-oriented programming if you like, but I
did not use aspects. I broke into the boot classloader also. For
instrumentation,
I use JikesBT (http://www.alphaworks.ibm.com/tech/jikesbt), which will be
refreshed on AlphaWorks soon.

I spent a considerable amount of energy in making performance acceptable.
My first try was to do the transformation during classloading, but I soon
learned this does not scale. Instrumentation is an order of magnitude more
expensive than plain classloading.

This is a very good point. I observed pretty much the same problems with my modified runtime. If many classes got woven the performance is not really acceptable. Therefore I am spending some time on optimising the way the weaver detects whether a class has to be woven or not. For example: If I write an aspect that uses the within pointcut designator the weaver could easily determine whether a specific class (to be loaded) has to be passed to the weaver or not. This way I can avoid to go into the time-consuming weaving (and bytecode modification) process for most classes, if the aspects are defined this way.

But this helps only in the case the aspect pointcuts are defined in a "weaver-fastfind-pointcut-member"-friendly way. The worst case is still that all classes have to be woven.



So, currently I use a cached approach. The crosscuts are applied to the
classfiles
when the plugin they live in is first loaded. Then the result is cached. So,
you
only have to wait once (during "installation"). Future loads of the platform
will
be (almost) as fast as before.

Just to give you an idea, I instrumented all plugins in IBM WSAD (450
plugins),
and record #all# method enter/leave events, parameter values, and memory
allocations.
Loading the platform is about 2 times the original load time. Most of the
delay is
caused because I start recording memory allocations as soon as possible to
address "memory leaks" in plugins later.

During a "normal" WSAD session (open a few EJBs, do a remote webservice),
you
easily load close to 150-200 plugins. Instrumenting those plugins takes
about 20
minutes of 100% CPU. Using instrumentation during classloading would render
your techniques impractical for "real use".

Concluding, I strongly recommend adopting a caching mechanism.

I think this is a very good idea. We could cache the modified bytecode of loaded classes somewhere (in the metadata area?).
In this case we need a mechanism to determine whether the aspects have changed since the last time the system was started. The numer of aspects (or a map to figure out which aspects way installed last time and which not) would not be enough. An installed aspect itself might have changed. If, for example, the pointcut definition is changed the aspect needs to be rewoven into the system the next time the system starts.


Any ideas on that?

Best regards,
Martin


BTW: Cool screenshots. Looks great. Did you post them somewhere on the web?


Chris Laffra



"Martin Lippert" <lippert@xxxxxxx> wrote in message
news:b6cj17$1fe$1@xxxxxxxxxxxxxxxx

Hi,

just one word before I start to explain the modifications. I have
implemented a modified version of the Eclipse runtime which allows you
to define aspects in single plugins. As long as the aspects are promoted
via a special extension (to a new extension point) that got woven into
the complete system if defined so in the pointcut definition of the
aspect. The current implementation is based on Eclipse 2.1 RC2 and
AspectJ 1.1rc1 and it really works. So if anybody would like to see and
try it, just drop me an email.

And now some more details on what I would like to have to implement the
dynamic weaving inside a separate plugin (currently it is directly
injected into the boot and runtime plugins):


Bytecode modification at class loading time: -------------------------------------------- A new extension point that allows me to declare bytecode transformer components inside a plugin. The extension point could be defined by the boot or the runtime plugin. Which one to take depends on whether the boot or the runtime plugin should include a modification to the class loader to call possible extensions (bytecode transformers) before the loaded bytecode is given to the VM.

Extension Point definition:

Something like:
<extension-point name="%bytecodetransformerName"

id="bytecodetransformers"/>

Interface for the extension point:

public interface BytecodeTransformer {

public byte[] transformBytecode (Resource classResource, String pluginId);

}

(The classResource parameter is used to get the real bytecode as well as
the URL from where the bytecode is loaded. The plugin id parameter is
used to let the bytecode transformer component know to which plugin the
class belongs that got modified. This information is used to handle the
dependencies between the plugins, see next point.)

To realize this kind of transformer extension point the runtime or boot
plugin has to implement the class loading directly inside the Eclipse
specific class loaders instead of delegating it to the JDK
URLClassLoader superclass. This is necessary because the URLClassLoader
does not allow a subclass to inject functionality while the bytecode of
a class is loaded.


Handling dependencies between plugins dynamically: -------------------------------------------------- While aspects are woven into classes (of possibly each plugin) new dependencies between plugins might be introduced. This has to be put in place by the bytecode transformer when it happens. Therefore the bytecode transformer needs some kind of method “addImport” at the DelegatingURLClassLoader.


Initialization of the transformer components: --------------------------------------------- The transformer components have to be initialized before the real application is started by the runtime (to make sure that the bytecode modification reaches all classes of the system, except boot and runtime of course). Currently I coded this into the InternalPlatform’s loaderStartup method.


Any opinions on that?


Best regards, Martin



Jeff McAffer wrote:


I second Peter's interest.  It would also be interesting to have some
usecases to motivate this in a plugin setting.

Jeff

"pkriens" <Peter.Kriens@xxxxxxxx> wrote in message
news:3E87FE7E.3090406@xxxxxxxxxxx


I think it is a great idea to see if this weaving could be done in
runtime. It is something I discussed at the OOPSLA 3 years ago with the
AspectJ people but I then understood it weaving could basically only be
done with the sources.

I seen several applications in the OSGi world where this might be very
useful. Unfortunately, aspect oriented programming is not very well
known among embedded developers (and there are of course the size
impacts). Can you describe more in detail the API you would need from
the class loaders to make this possible? Or do you have pointers to
papers? I'd like to propose this to some of the OSGi vendors.

Thanks, kind regards,

Peter Kriens

Martin Lippert wrote:



Hi all,

my name is Martin (Lippert) and I am new to this group. Brian Barry and
Jeff (McAffer) told me that this might be the right place to talk about
my ideas. So I hope you are interested in it, even if it might sounds a
bit strange at first sight.

During the last weeks and months I had the idea of bringing AspectJ and
the Eclipse plugin model closer together by allowing people to develop
applications using both, aspects written in AspectJ and plugins using
the Eclipse runtime. They would be able to write aspects in AspectJ,
compile them with their compiler (or the respective plugin for the Java
Tooling inside Eclipse) and plug them into the system as a normal
plugin. The main motivation is that people are interested in both:
plugins as their base runtime infrastructure and aspects to modularize
crosscutting concerns.

I thought about load-time weaving to allow them to individually develop
each plugin. Today, they can use an aspect only inside a single plugin,
because the compiler weaves the aspect into the other classes. With
load-time weaving the idea of Eclipse to encapsulate each plugin (even
with aspects that define cross-plugin pointcuts) would become possible
for aspects.

So I implemented a modified version of the core plugins (boot and
runtime) to realize this behavior and demonstrated it at the AOSD
conference last week. The feedback was very positive and I would like

to

continue to improve the implementation and make it available to the
people who are interested.
The only thing that makes this a bit complicated is the fact that I had
to implement a modified version of the base plugins. It was not

possible

to write a plugin that enhances the runtime in the way I want it to be.

The main reasons for this:
- I had to inject the weaving at class-loading time. The current class
loader of Eclipse do not allow me to enhance their behavior for such
kind of things.
- I had to add dependencies between plugins at runtime (depending on
which aspect got woven into which class).
- I had to add some setup code that got called after the registry is
initialized but before the application starts.

And this is exactly the point where it might be interesting for this
project. These are exactly the points where I would love to make the
runtime more flexible. This might seem a bit strange (especially the
load-time modifications of classes), but the load-time weaving of
aspects opens a totally new world of possibilities for aspects and
plugins used together.

So I am highly interested in hearing your opinions on that. I can also
provide more technical details of the possible enhancements to the
runtime. I would also love to contribute some code for this kind of
modifications, if possible. What do you think?

Best regards,
Martin Lippert


--- Martin Lippert email: lippert@xxxxxxx