Перемещение пакетов AspectJ в агенте Java

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

person Shalom938    schedule 20.11.2017    source источник
comment
В какое время происходит что? Это время загрузки или время компиляции? Когда происходит это затенение?   -  person Tamas Rev    schedule 12.12.2017
comment
@TamasRev, время загрузки увеличивается. перемещение происходит во время сборки с использованием gradle при упаковке jar агента.   -  person Shalom938    schedule 12.12.2017


Ответы (3)


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

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

shadowJar {
    tranform(XmlAppendingTransformer.class) {
        resource = 'aop.xml'
    }
}
person Devstr    schedule 15.12.2017
comment
работает без тени? Похоже, ваше исключение происходит отсюда github.com/eclipse/org.aspectj/blob/ Я бы попробовал подключить отладчик и пройтись по коду. Глядя на реализации метода isAspect, я вижу некоторые подозрительные вещи, такие как: /ajdt/internal/compiler/lookup/EclipseSourceType.java#L176" rel="nofollow noreferrer">github.com/eclipse/org.aspectj/blob/ - person Devstr; 19.12.2017
comment
Также попробуйте установить системное свойство -Dorg.aspectj.tracing.enabled=true, чтобы включить трассировку AspectJ. Так вы получите больше информации о том, что происходит. см. github.com/eclipse/org.aspectj/blob/ - person Devstr; 19.12.2017

Я не думаю, что это проблема. Я не перемещаю свои классы аспектов, а только зависимости, такие как библиотека 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 аннотация. аспект jweaver проверяет аннотацию, используя строковую константу. это происходит в org.aspectj.weaver.bcel.BcelWeaver#addLibraryAspect, и константа используется, например, так:

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

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

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

person Shalom938    schedule 19.12.2017

Вы можете попробовать исключить аннотацию 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.

person Devstr    schedule 19.12.2017
comment
мой ответ на ваше предложение выше, не мог написать его как комментарий. - person Shalom938; 20.12.2017