在Java代理中重新定位AspectJ包

12

我正在使用AspectJ监控字段访问和修改。 我有一个Gradle项目,可以编译这两个方面,并将其与aspectjrt和aspectjweaver一起打包到一个阴影jar中,使用Gradle Shadow插件。 代理仍然是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

什么时候发生了什么?是在加载时间还是编译时织入?这个遮蔽是什么时候发生的? - Tamas Rev
@TamasRev,这是加载时编织。在打包代理jar时,重定位会在构建时使用gradle发生。 - Shalom938
3个回答

1

请检查阴影 jar 内的 aop.xml 文件内容。方面类名是否被遮蔽?根据错误消息,我认为它不会被遮蔽。

如文档中所述, 您可以使用 Shadow 插件转换 XML 文件,例如:

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

它是否没有阴影效果?看起来你的异常是从这里发起的:https://github.com/eclipse/org.aspectj/blob/8dda42d0272eb4fdc157282880caf915a9e33ea1/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java#L223我建议尝试附加调试器并逐步执行代码。查看“isAspect”方法的实现,我发现一些可疑的事情,比如这个: https://github.com/eclipse/org.aspectj/blob/03752862ba3bc6ef132195673903dcf9109e8b93/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java#L176 - Devstr
另外,还可以尝试设置系统属性“-Dorg.aspectj.tracing.enabled=true”以启用AspectJ跟踪。这样,您就可以更深入地了解发生了什么。请参阅https://github.com/eclipse/org.aspectj/blob/eb5b2857783d3060a5a3188a3811f5cbb8f81aa5/org.aspectj.matcher/src/org/aspectj/weaver/tools/DefaultTraceFactory.java#L20 - Devstr

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;")

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

我很确定这就是问题所在。


1

我的回答在你的建议上方,无法以评论形式写出来。 - Shalom938

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接