Relocating AspectJ packages in a Java agent
Asked Answered
H

3

12

I'm using AspectJ to monitor field access and field modify. I have a gradle project that compiles the two aspects and package that jar together with the aspectjrt and aspectjweaver in a shaded jar using gradle shadow plugin. the agent is still org.aspectj.weaver.loadtime.Agent. everything works fine, but when i try to relocate the aspectj packages I get an error.

The shadow plugin configuration is:

shadowJar {
    relocate 'org.aspectj', 'shadow.org.aspectj'
    relocate 'aj.org.objectweb.asm', 'shadow.aj.org.objectweb.asm'
}

The manifest :

jar {
    manifest {
        attributes("Premain-Class": "shadow.org.aspectj.weaver.loadtime.Agent",
                "Can-Redefine-Classes": true,
                "Can-Retransform-Classes":true)
    }
}

This is the decompiled aspect class so it seems correct:

package com.vfunction.singletonanalysis;

import shadow.org.aspectj.lang.JoinPoint;
import shadow.org.aspectj.lang.NoAspectBoundException;
import shadow.org.aspectj.lang.annotation.Aspect;
import shadow.org.aspectj.lang.annotation.Before;

@Aspect
public class StaticFieldBeforeAccessAspect extends AbstractFieldAccessAspect {
    public StaticFieldBeforeAccessAspect() {
    }

    @Before("callAt()")
    public void before(JoinPoint joinPoint) throws Throwable {
        this.printJoinPoint(joinPoint);
    }

    public static StaticFieldBeforeAccessAspect aspectOf() {
        if (ajc$perSingletonInstance == null) {
            throw new NoAspectBoundException("com.vfunction.singletonanalysis.StaticFieldBeforeAccessAspect", ajc$initFailureCause);
        } else {
            return ajc$perSingletonInstance;
        }
    }

    public static boolean hasAspect() {
        return ajc$perSingletonInstance != null;
    }

    static {
        try {
            ajc$postClinit();
        } catch (Throwable var1) {
            ajc$initFailureCause = var1;
        }

    }
}

But I still get an error when trying to run a test program saying the the type found is not an aspect:

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.8.12 built on Friday Oct 20, 2017 at 21:58:11 GMT
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info using configuration file:***/workspace/singleton-analysis/agent/build/libs/agent-1.0.0-SNAPSHOT-all.jar!/META-INF/aop.xml
[AppClassLoader@18b4aac2] info register aspect com.vfunction.singletonanalysis.StaticFieldModifyAspect
[AppClassLoader@18b4aac2] error The specified aspect 'com.vfunction.singletonanalysis.StaticFieldModifyAspect' cannot be found
[AppClassLoader@18b4aac2] info register aspect com.vfunction.singletonanalysis.StaticFieldAccessAspect
[AppClassLoader@18b4aac2] error The specified aspect 'com.vfunction.singletonanalysis.StaticFieldAccessAspect' cannot be found
[AppClassLoader@18b4aac2] info register aspect com.vfunction.singletonanalysis.StaticFieldBeforeAccessAspect
[AppClassLoader@18b4aac2] error Cannot register 'com.vfunction.singletonanalysis.StaticFieldBeforeAccessAspect' because the type found with that name is not an aspect
Hershberger answered 20/11, 2017 at 13:53 Comment(2)
At what time happens what? Is it loadtime or compile time weaving? When does this shadowing happen?Elect
@TamasRev , its load time weaving. relocation happens at build time using gradle when packaging the agent jar.Hershberger
R
1

Check contents of aop.xml inside the shaded jar. Is the aspect class name shadowed? I would suspect that it's not given the error message.

As mentioned in documentation, you can make Shadow plugin transform XML files like this:

shadowJar {
    tranform(XmlAppendingTransformer.class) {
        resource = 'aop.xml'
    }
}
Rabid answered 15/12, 2017 at 18:3 Comment(2)
does it work without shadowing? It looks like your exception originates from here github.com/eclipse/org.aspectj/blob/… I would try attaching a debugger and stepping through the code. Looking at implementations of isAspect method I see some suspicious things like this: github.com/eclipse/org.aspectj/blob/…Rabid
Also try setting System property "-Dorg.aspectj.tracing.enabled=true" to enable AspectJ tracing. That way you'll get more insight into what's going on. see github.com/eclipse/org.aspectj/blob/…Rabid
H
1

I don't think that's the issue. I do not relocate my aspect classes, only the dependencies like aspectj library. so my aspect class looks like that:

import com.vfunction.jni.Callbacks;
import java.lang.reflect.Field;
import vshadow.org.aspectj.lang.JoinPoint;
import vshadow.org.aspectj.lang.annotation.Aspect;
import vshadow.org.aspectj.lang.annotation.Before;
import vshadow.org.aspectj.lang.annotation.Pointcut;

@Aspect
public class StaticFieldBeforeModifyAspect extends AbstractFieldAccessAspect

as you see it imports vshadow.org.aspectj.lang.annotation.Aspect , that class exists. the issue is that the aspectjweaver code checks if a class is a valid aspect by inspecting if the class has an org.aspectj.lang.annotation.Aspect annotation, but it doesn't ,it has a vshadow.org.aspectj.lang.annotation.Aspect annotation. the aspectjweaver checks for the annotation using a string constant. it happens in org.aspectj.weaver.bcel.BcelWeaver#addLibraryAspect and the constant is used like that for example:

public final static UnresolvedType ASPECT_ANNOTATION = UnresolvedType.forSignature("Lorg/aspectj/lang/annotation/Aspect;")

and the shadow plugin does not relocate that.

I'm pretty sure that's the issue.

Hershberger answered 19/12, 2017 at 16:16 Comment(0)
R
1

You can try excluding Aspect annotation from shadowing:

shadowJar {
   relocate('org.aspectj', 'shadow.org.aspectj') {
       exclude 'org.aspectj.lang.annotation.Aspect'
   }
}

see http://imperceptiblethoughts.com/shadow/#relocating_packages

Another hacky option is to write your own Transformer that will search and replace "Lorg/aspectj/lang/annotation/Aspect;" with shadowed version.

see http://imperceptiblethoughts.com/shadow/#controlling_jar_content_merging

Rabid answered 19/12, 2017 at 17:38 Comment(1)
my answer to your suggestion is above, couldn't write it as comment.Hershberger

© 2022 - 2024 — McMap. All rights reserved.