在Java代理中重定位AspectJ包

时间:2017-11-20 13:53:07

标签: java aspectj javaagents

我正在使用AspectJ来监控字段访问和字段修改。我有一个gradle项目,它编译了两个方面,并使用gradle shadow插件将jar与aspectjrt和aspectjweaver打包在一个带阴影的jar中。 代理仍然是org.aspectj.weaver.loadtime.Agent。 一切正常,但是当我尝试重新定位aspectj包时,我得到一个错误。

影子插件配置为:

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

清单:

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

这是反编译的方面类,所以看起来是正确的:

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;
        }

    }
}

但是在尝试运行测试程序时仍然会出错,说找到的类型不是方面:

[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

3 个答案:

答案 0 :(得分:1)

检查阴影罐内aop.xml的内容。 方面类名称是否为阴影?我怀疑它没有给出错误信息。

As mentioned in documentation,您可以使Shadow插件转换为以下XML文件:

shadowJar {
    tranform(XmlAppendingTransformer.class) {
        resource = 'aop.xml'
    }
}

答案 1 :(得分:1)

我认为这不是问题。我不重新定位我的方面类,只重新定位像aspectj库这样的依赖项。所以我的方面类看起来像这样:

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

如你所见导入vshadow.org.aspectj.lang.annotation.Aspect,该类存在。 问题是aspectjweaver代码通过检查类是否具有org.aspectj.lang.annotation.Aspect注释来检查类是否是有效方面,但它没有,它有一个vshadow.org.aspectj.lang。 annotation.Aspect注释。 aspectjweaver使用字符串常量检查注释。 它发生在org.aspectj.weaver.bcel.BcelWeaver#addLibraryAspect中 并且常量用于例如:

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

并且影子插件不会重新定位。

我很确定这是问题。

答案 2 :(得分:1)

您可以尝试从遮蔽中排除Aspect注释:

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

请参阅http://imperceptiblethoughts.com/shadow/#relocating_packages

另一个hacky选项是编写自己的Transformer,它将使用阴影版本搜索和替换"Lorg/aspectj/lang/annotation/Aspect;"

请参阅http://imperceptiblethoughts.com/shadow/#controlling_jar_content_merging