Подтвердить что ты не робот

Перенос пакетов AspectJ в Java-агенте

Я использую AspectJ для контроля доступа к полям и изменения поля. У меня есть проект gradle, который компилирует два аспекта и пакет, которые объединяются вместе с аспектным и аспектным файлом в затененной банке с помощью теневого плагина gradle. агент по-прежнему является 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;
        }

    }
}

Но я все еще получаю сообщение об ошибке при попытке запустить тестовую программу, заявив, что найденный тип не является аспектом:

[[email protected]] info AspectJ Weaver Version 1.8.12 built on Friday Oct 20, 2017 at 21:58:11 GMT
[[email protected]] info register classloader [email protected]
[[email protected]] info using configuration file:***/workspace/singleton-analysis/agent/build/libs/agent-1.0.0-SNAPSHOT-all.jar!/META-INF/aop.xml
[[email protected]] info register aspect com.vfunction.singletonanalysis.StaticFieldModifyAspect
[[email protected]] error The specified aspect 'com.vfunction.singletonanalysis.StaticFieldModifyAspect' cannot be found
[[email protected]] info register aspect com.vfunction.singletonanalysis.StaticFieldAccessAspect
[[email protected]] error The specified aspect 'com.vfunction.singletonanalysis.StaticFieldAccessAspect' cannot be found
[[email protected]] info register aspect com.vfunction.singletonanalysis.StaticFieldBeforeAccessAspect
[[email protected]] error Cannot register 'com.vfunction.singletonanalysis.StaticFieldBeforeAccessAspect' because the type found with that name is not an aspect
4b9b3361

Ответ 1

Проверьте содержимое aop.xml внутри затененной банки. Является ли имя класса аспект затененным? Я подозреваю, что он не дал сообщение об ошибке.

Как уже упоминалось в документации, вы можете сделать XML файлы Transform плагина следующим образом:

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

Ответ 2

Я не думаю, что проблема. Я не перемещаю свои классы аспект, а только зависимости, такие как aspectj library. поэтому мой класс аспект выглядит следующим образом:

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 annotation, но это не так, у него есть vshadow.org.aspectj.lang. Аннотации. Аннотации. aspectjweaver проверяет аннотацию с использованием строковой константы. это происходит в org.aspectj.weaver.bcel.BelWeaver # addLibraryAspect и константа используется так, например:

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

и теневой плагин не переносит это.

Я уверен, что проблема.

Ответ 3

Вы можете попробовать исключить аннотацию Aspect от теневого копирования:

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

см. http://imperceptiblethoughts.com/shadow/#relocating_packages

Другой хакерский вариант - написать собственный Transformer, который будет искать и заменять "Lorg/aspectj/lang/annotation/Aspect;" теневой версией.

см. http://imperceptiblethoughts.com/shadow/#controlling_jar_content_merging

Ответ 4

Исключение org.aspectj.lang.annotation.Aspect не работает, и я получаю ту же ошибку:

Ошибка Не удается зарегистрировать 'Com.vfunction.singletonanalysis.StaticFieldBeforeModifyAspect' потому что тип, найденный с этим именем, не является аспектом

Итак, я попробовал исключить весь пакет lang:

переместить ('org.aspectj', 'vshadow.org.aspectj') {         исключить 'org.aspectj.lang.annotation. *'     }

в этом случае аспекты, которые есть до и после работы совета, но аспекты вокруг совета не работают, и мы получаем это исключение:

Исключение в потоке "main" java.lang.reflect.InvocationTargetException   at sun.reflect.NativeMethodAccessorImpl.invoke0 (Нативный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)   в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)   в java.lang.reflect.Method.invoke(Method.java:498) в sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)   в sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401) Причина: java.lang.NoSuchMethodError: shadow.org.aspectj.runtime.internal.AroundClosure.linkClosureAndJoinPoint(I) Lorg/AspectJ/языки/ProceedingJoinPoint;

Он считает, что исключение некоторых классов aspectj вызовет неправильное поведение aspectj