I looked through AspectJ's Load Time Weaver and I combined it with your code suggestion.
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;
}
}
I tried it on Java 1.6.0_15 on Mac OSX.