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?

Hello,

I looked through AspectJ's Load Time Weaver and I combined it with your code suggestion.
This is what I got out

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aspectj.weaver.loadtime.Aj;
import org.aspectj.weaver.loadtime.DefaultWeavingContext;
import org.aspectj.weaver.loadtime.definition.Definition;
import org.aspectj.weaver.tools.WeavingAdaptor;

public class AspectJLTW implements ClassFileTransformer {

private class MonitorWeavingContext extends DefaultWeavingContext {

public MonitorWeavingContext(ClassLoader loader) {
super(loader);
}

@Override
public List getDefinitions(ClassLoader loader, WeavingAdaptor adaptor) {
List definitions = new ArrayList();
Definition d = new Definition();
d.getAspectClassNames().add(aspectName);
d.appendWeaverOptions("-Xjoinpoints:synchronization");
definitions.add(d);
return definitions;
}

}

private final Map<ClassLoader, Aj> mapFromClassLoaderToAj;
private final String aspectName;

public AspectJLTW(String aspectName) {
try {
mapFromClassLoaderToAj = new ConcurrentHashMap<ClassLoader, Aj>();
this.aspectName = aspectName;
} catch (Exception e) {
throw new ExceptionInInitializerError(
"could not initialize JSR163 preprocessor due to: "
+ e.toString());
}
}

/**
* Weaving delegation
* @param loader
*            the defining class loader
* @param className
*            the name of class beeing loaded
* @param classBeingRedefined
*            when hotswap is called
* @param protectionDomain
* @param bytes
*            the bytecode before weaving
* @return the weaved bytecode
*/
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] bytes) throws IllegalClassFormatException {
if (className.replace("/", ".").equals(aspectName))
return null;
Aj aj = getInstrumenter(loader);
byte[] b = aj.preProcess(className, bytes, loader);
if (Arrays.equals(bytes, b))
return null;
return b;
}

private Aj getInstrumenter(ClassLoader loader) {
if (mapFromClassLoaderToAj.containsKey(loader)) {
return mapFromClassLoaderToAj.get(loader);
}
Aj aj = new Aj(new MonitorWeavingContext(loader));
mapFromClassLoaderToAj.put(loader, aj);
return aj;
}
}

If you add "-Xbootclasspath/p:<path_to_aspects.jar>" JVM option, then you can instrument inside the JDKs and also instrument already loaded classes.
I tried it on Java 1.6.0_15 on Mac OSX.

One little note: JVM complains about java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields). I suspect t has something to do with AspectJ adding extra fields. Is there a way to force inlining of the aspects?

Best regards,
Silviu
On Nov 22, 2009, at 12:18 AM, Andy Clement wrote:

the code I posted was just an alternative way to interact with the
load time weaver.  I didn't mean anything with bootclasspath.

Andy


2009/11/21 Andrica Silviu <silviu.andrica@xxxxxxx>:
Hi,

when you say this is an alternative way, what do you exactly mean? An alternative way to the code I posted or an alternative way to -Xbootclasspath, which, BTW, does not work. Crashes the JVM.

Cheers,
       Silviu
On Nov 21, 2009, at 11:10 PM, Andy Clement wrote:

Glad to see you got it working.

There is an alternative way too. It involves defining a correct
weaving context that names the aspects and your options:

static class SimpleWeavingContext extends DefaultWeavingContext {

              public SimpleWeavingContext(ClassLoader loader) {
                      super(loader);
              }

              @Override
              public List getDefinitions(ClassLoader loader, WeavingAdaptor adaptor) {
                      List definitions = new ArrayList();
                      Definition d = new Definition();
                      d.getAspectClassNames().add("MonitorAspect");
                      d.appendWeaverOptions("-Xjoinpoints:synchronization -debug");
                      definitions.add(d);
                      return definitions;
              }

      }


and then using the ClassLoaderWeavingAdaptor:

              byte[] bytes = readEntireInputStream(new FileInputStream("bin/Test.class"));
              URL[] aspects = getWeaversURL();
              URL[] classpath = getClasspathURL();
              URL[] realClasspath = new URL[aspects.length + classpath.length];
              System.arraycopy(aspects, 0, realClasspath, 0, aspects.length);
              System.arraycopy(classpath, 0, realClasspath, aspects.length,
classpath.length);
              URLClassLoader myClassLoader = new URLClassLoader(realClasspath,
ClassLoader.getSystemClassLoader());

              ClassLoaderWeavingAdaptor clwa = new ClassLoaderWeavingAdaptor();

              clwa.initialize(myClassLoader, new SimpleWeavingContext(myClassLoader));

              byte[] newBytes = clwa.weaveClass("test.Test", bytes, true);

However, it will only work with AspectJ 1.6.7 dev builds after today
because I needed to open up initialize() so it was public rather than
protected. And I've only just committed that change.

Andy


2009/11/21 Andrica Silviu <silviu.andrica@xxxxxxx>:
Hi,
Indeed I forgot :) And I did create a wrapper class around the
WeavingAdaptor that sets the right permissions. The code is the following:
Please find attached the code.
It works brilliant as long as I don't instrument already loaded classes,
through java.lang.Instrumentation.instrumentation.retransformClasses(...);
or java.* classes, I don't exactly know. In this case, Java complains about
not finding the aspect. I am currently exploring the use of
-Xbootclassptah/p:<path_to_aspect>.

Thanks for the replies.
Best regards,
Silviu
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top