>> 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 - you can use the bootclasspath option to instrument system classes that ordinarily are beyond your reach because they have been loaded before the weaver has been initialized. AspectJ doesn't offer anything special in terms of instrumentation or dynamic modification of already loaded classes. But it attempts to play nicely with whatever you are attempting to use to do that. For example if running in debug mode with -javaagent:aspectjweaver, and you change a type that was woven through loadtime weaving, when the debugger attempts to hotswap the new version in, the weaver will weave it again (IIRC). If you are reloading by discarding a classloader and recreating it, a new weaver instance will be used for the new classloader and do the weaving again. > I am interested in the second option (the former afterwards maybe). How do > you use this class to instrument and replace an already loaded class? I mean > do you have a code snippet showing which parameters you submit to "transform" > and hoow to replace an already loaded class? Specifically: > - Which loader do you use? A WeavingURLClassLoader or the loader the > weaving target was initially loaded by? If you were using a classloader strategy to discard/reload code and not using -javaagent then you might use a WeavingURLClassLoader. But the WeavingURLClassLoader is not going to be noticing files changing on disk that need reloading and managing the deletion/creation of the classloader instances. > - Where does the byte array for the class to be woven come from? In the basic scenario it comes from the debugger in your ide... For other kinds of solution you have to have something noticing the class files are changing and pushing the change in. For example the reloading agent that Grails uses does this. It monitors the files system, sees a .class file has changed, picks up the bytecode and pushes into the reloading agent. In principal the grails reloading technology (springloaded) can be reused in a standalone setting to achieve the reloading of woven code, but I haven't done a lot of testing of this setup. > Can I get the class's bytes somehwere from memory or do I need > to re-load the actual .class file from disk/URL/JAR/whatever? A monitoring solution will be watching disk, load them from there and pass them to the weaver to weave again, and then reload the result of that weaving. it is quite a complex area... Andy > Silviu Andrica wrote in 2009: >> 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? > _______________________________________________ > aspectj-users mailing list > aspectj-users@eclipse.org > https://dev.eclipse.org/mailman/listinfo/aspectj-users _______________________________________________ aspectj-users mailing list aspectj-users@eclipse.org https://dev.eclipse.org/mailman/listinfo/aspectj-users