ClassNotFoundException в аспекте при использовании proguard

1

У меня проблема с моим классом аспектов, когда я обманываю свои коды с помощью proguard.

У меня есть аспект, который обнаруживает все методы с аннотацией @Cacheable.

Вот пример класса, который содержит аннотацию @Cacheable

package com.mycompany.user;

public class User {

    @Cacheable(scope="session", uniqueName="userInfo")
    public UserInfo getUserInfo(Long userId) {
       ...
    }
}

и вот мой код аспекта:

@Aspect
public class CacheMethodResultAspect {
    @Around(
            value = "execution(@com.mycompany.cache.Cacheable * *.*(..))",
            argNames = "proceedingJoinPoint,joinPointStaticPart"
    )
    public Object retrieveResultFromCache(ProceedingJoinPoint proceedingJoinPoint, JoinPoint.StaticPart joinPointStaticPart)
            throws Throwable {

        final CacheScope cacheScope = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod().getAnnotation(Cacheable.class).scope();
        final CacheConstants uniqueName = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod().getAnnotation(Cacheable.class).uniqueName();
        final String methodLine = proceedingJoinPoint.getSignature().getDeclaringTypeName() + "." + proceedingJoinPoint.getSignature().getName()
                + "@" + joinPointStaticPart.getSourceLocation().getLine();

                .
                .
                .
    }

}

когда я регистрирую результат continueJoinPoint, он возвращает следующую строку:

execution(UserInfo java.lang.ClassNotFoundException.getUserInfo())

Я ожидаю, что он вернет этот результат:

execution(UserInfo com.mycompany.user.getUserInfo())

он определяет только имя метода! поэтому я не могу получить аннотацию @Cacheable для этого метода!

я не хочу использовать:

-keep class myClassName...

Аспектная версия: 1.6.12

версия java: 1.7 обновление 21

версия для proguard: 4.9

любая помощь будет оценена.

  • 0
    Я хотел бы помочь, потому что я знаю и ProGuard, и AspectJ, но ваш вопрос настолько неясен и противоречив, что я не могу понять вашу проблему. Пожалуйста, отредактируйте вопрос и объясните более точно. Если ваш английский слишком плохой, нет проблем: пусть код говорит и покажите нам больше кода.
  • 0
    извиняюсь. я отредактировал свой вопрос :)
Показать ещё 4 комментария
Теги:
obfuscation
proguard
aspectj

1 ответ

3
Лучший ответ

Хорошо, это было очень сложно, но, наконец, я смог воспроизвести проблему с неправильной MethodSignature хранящейся в этом thisJoinPointStaticPart. Я попробовал много опций ProGuard, но, наконец, я обнаружил, что -adaptclassstrings был недостающим. Очевидно, что AspectJ использует имена классов, закодированные в строках - возможно, что-то похожее на Class.forName(), я не проверял код байта.

Самая важная часть конфигурации ProGuard Maven Plugin:

<configuration>
    <options>
        <option>-target 1.7</option>
        <option>-adaptclassstrings</option>
        <option>-keepclasseswithmembers public class * { public static void main(java.lang.String[]); }</option>
        <option>-keepattributes *Annotation*</option>
        <option>-keepclassmembernames class * { @de.scrum_master.app.Cacheable *** **(...); }</option>
    </options>
    <libs>
        <lib>${java.home}/lib/rt.jar</lib>
        <!--<lib>${java.home}/lib/jsse.jar</lib>-->
    </libs>
</configuration>

Поскольку полное объяснение слишком велико, чтобы процитировать здесь полный код образца и т.д., Я создал для вас проект GitHub. Пожалуйста, проверьте код и настройки Maven для ProGuard. Вы можете просто клонировать репозиторий и звонить

mvn install

Я сделал это очень удобно для вас, я даже включил шаг сборки OneJAR, поэтому после сборки вы можете просто позвонить

java -jar target/aspectj-proguard-1.0-SNAPSHOT.one-jar.jar

из каталога проекта. Результат должен выглядеть следующим образом:

User{id=1, info=UserInfo{info='First'}}
User{id=2, info=UserInfo{info='Second'}}
User{id=3, info=UserInfo{info='Third'}}
User{id=4, info=UserInfo{info='Fourth'}}
User{id=5, info=UserInfo{info='Fifth'}}
execution(d de.scrum_master.app.b.getUserInfo(Long))
  Cacheable scope:       session
  Cacheable unique name: userInfo
  Method line:           de.scrum_master.app.b.getUserInfo@27
UserInfo{info='First'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
  Cacheable scope:       session
  Cacheable unique name: userInfo
  Method line:           de.scrum_master.app.b.getUserInfo@27
UserInfo{info='Third'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
  Cacheable scope:       session
  Cacheable unique name: userInfo
  Method line:           de.scrum_master.app.b.getUserInfo@27
UserInfo{info='Fifth'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
  Cacheable scope:       session
  Cacheable unique name: userInfo
  Method line:           de.scrum_master.app.b.getUserInfo@27
null

Дополнительные подсказки:

  • Я использовал собственный синтаксис AspectJ вместо синтаксиса @AspectJ на основе аннотаций, потому что это тот вкус, который мне больше нравится. Но код достаточно похож на ваш пример, чтобы быть легко конвертируемым. Возможно, вам нужны еще несколько статей для ProGuard для аннотаций @AspectJ, но это должно быть тривиально.
  • В репозитории Git есть два тега: single_project (последняя фиксация с одним модулем Maven, содержащая все) и multi_project (старший фиксатор с тремя модулями Maven, один для основного приложения, один для аннотаций и один для аспектов). Вы можете сравнить оба варианта, если хотите.

Наслаждайтесь! Надеюсь, это решит вашу проблему. :-)

Обновление: я забыл упомянуть, как точно воспроизвести проблему: просто удалите <option>-adaptclassstrings</option>, перестройте и снова запустите программу:

(...)
User{id=5, info=UserInfo{info='Fifth'}}
execution(ClassNotFoundException java.lang.ClassNotFoundException.getUserInfo(Long))
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.simontuffs.onejar.Boot.run(Boot.java:306)
        at com.simontuffs.onejar.Boot.main(Boot.java:159)
Caused by: java.lang.NullPointerException
        at de.scrum_master.a.a.a(Unknown Source)
        at de.scrum_master.app.b.getUserInfo(Unknown Source)
        at de.scrum_master.app.Application.main(Unknown Source)
        ... 6 more
  • 0
    Спасибо kriegaex :) ты потрясающий :) это работает как шарм;)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню