Gonny
Gonny

Reputation: 143

Load time weaving of javax.swing.* classes with AspectJ

I am using AspectJ to trace calls to graphics class. So far, I have used a pre-weaved set of javax.swing.* classes and upon loading I tell JVM to use these weaved classes and not the ones from JRE by using -Xbootclasspath/p switch.

I would like to switch to load time weaving mode. Can anyone help me how to weave javax.swing on load time. I have searched the net but still I cannot figure it out how to do it. I know that by default, AspectJ load time weaver will not weave java.* and javax.* classes. Someone suggested using

-Xset:weaveJavaPackages=true,weaveJavaxPackages=true

in aop.xml but none of this helped because javax.swing classes are loaded before the weaver is attached to the classloader. I guess that the weaver does not see these classes at all.

How can I manage to dynamically weave javax.swing classes? Should I implement a custom class loader that first registers a weaver then does the class loading?

Can someone please suggest any solution?

Upvotes: 6

Views: 1913

Answers (3)

kriegaex
kriegaex

Reputation: 67287

The only solution I can suggest if you need to use execution() pointcuts for javax packages is to binary-weave the JRE's tools.jar and create your own, woven version. I have done that in the past, it worked nicely. But this is only an option if you have control over the runtime environment running your application.

If you do not want to use such an approach, you will have to resort to call() pointcuts. This way you can capture calls made by your own application or any 3rd party libraries affected by LTW. Only calls made by JRE classes loaded by the boot classloader will escape your aspect, which should not be too bad.

Upvotes: 2

manocha_ak
manocha_ak

Reputation: 902

Exactly you are halfway there Its not that hard, rather pretty straightforward.

<?xml version="1.0" encoding="UTF-8"?>
 <aspectj>
  <aspects>
 <aspect name="com.ciena.EDTCheck"/>
 </aspects>
    <weaver options="-Xset:weaveJavaxPackages=true -verbose">    
    </weaver>
  </aspectj>

Make sure that you have

aspectjweaver.jar in javaagent like -javaagent:C:\aspectj1.8\lib\aspectjweaver.jar

also make sure that your aop.xml above is in META-INF folder

that's all to run from Eclipse or some IDE

if you want to run from command line make sure that you give -javagaent there too

Upvotes: 0

kschneid
kschneid

Reputation: 5694

I'm by no means an expert, but while this looks promising:

Configuring Load-time Weaving with aop.xml files

Specifically:

<aspectj>
  <aspects>
    ...
  </aspects>
  <weaver options="-verbose">
    <!-- Weave types that are within the javax.* or org.aspectj.*
         packages. Also weave all types in the foo package that do
         not have the @NoWeave annotation. -->
    <include within="javax.*"/>
    <include within="org.aspectj.*"/>
    <include within="(!@NoWeave foo.*) AND foo.*"/>
    ... 
  </weaver>
</aspectj>

I'm not sure how it could work given the ClassPreProcessor used by the LTW's agent (although I haven't tried it). Here's the beginning of its preProcess method:

public byte[] preProcess(String className, byte[] bytes, ClassLoader loader, ProtectionDomain protectionDomain) {
    if (loader == null || className == null || loader.getClass().getName().equals(deleLoader)) {
        // skip boot loader, null classes (hibernate), or those from a reflection loader
        return bytes;
    }
    ...
    try {
        synchronized (loader) {
            ...
            WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
            ...
        }
    }
}

Which makes it pretty clear how boot loader classes are skipped. In addition, the WeaverContainer.getWeaver() invocation is what appears to trigger aop.xml processing, and that doesn't occur until after a class with a non-null loader is processed.

Not sure how much that helps with an actual solution, but hopefully it sheds some light on why things behave the way they do...

Upvotes: 1

Related Questions