2015-05-23 5 views
0

Примечание: это доказательство реализации концепции, а не последняя вещь.NoSuchMethodError с AspectJ

У меня есть 3-й. и я хочу ограничить их использование звука, например. ограничить продолжительность и т. д. (невозможно с менеджером безопасности). Для этого я подумал о замене возврата AudioSystem.getLine() оболочкой. это тест-аспект:

@Aspect 
public class MixerAspect { 
    @Around("execution(* javax.sound.sampled.AudioSystem.getLine(javax.sound.sampled.Line.Info))") 
    public Object getLineAdvice(ProceedingJoinPoint pjp) throws Throwable { 
     System.out.println("AspectJ"); 
     pjp.getArgs(); 
     Line ret = (Line) pjp.proceed(); 
     return ret; 
    } 
} 

каждая надстройка имеет свой собственный загрузчик классов, и они, как правило, не разделяют объекты, так это то, что я придумал:

@Override 
public Class<?> loadClass(String className) throws ClassNotFoundException { 
.... 
if (className.equals(AudioSystem.class.getName())) { 
    ..... 
    byte[] array = buffer.toByteArray(); 
     try { 
      if (mixed == null) 
       mixed = weaver.defineClass(className, array, new CodeSource(mixerAspect, (CodeSigner[]) null)); 
      return mixed; 
     } catch (IOException e) { 
      throw new ClassNotFoundException("unable to define class", e); 
     } 

это initlialization-код WeavingURLClassloader:

weaver = new WeavingURLClassLoaderHelper(new URL[0], parent); 
weaver.addURL(aspects[0]); 

родитель является загрузчиком классов с доступом к аспекту Mixer и аспектам URL-массив, единственный элемент которого является один указал на т он каталог, в котором MixerAspect находится в моей aop.xml:.

<aspectj> 
    <aspects> 
     <aspect name="org.intellimate.izou.security.replaced.MixerAspect"/> 
    </aspects> 

    <weaver options="-Xset:weaveJavaxPackages=true -verbose -showWeaveInfo -debug"> 
     <!-- Weave types that are within the javax.* or org.aspectj.* 
      packages. Also weave all types in the foo package that do 
      not have the @NoWeave annotation. --> 
     <include within="javax.*"/> 
     <include within="org.intellimate.izou.security.replaced.*"/> 
     <include within="javax.sound.sampled.AudioSystem"/> 
    </weaver> 
</aspectj> 

это (относится) журнал:

....(no relevant log) 
T[email protected]53aad5d5 
[WeavingURLClassLoaderHelper] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT 
[WeavingURLClassLoaderHelper] info register classloader ro.fortsoft.pf4j.IzouPluginClassLoader$WeavingURLClassLoaderHelper 
[WeavingURLClassLoaderHelper] info using configuration /Users/LeanderK/IdeaProjects/Izou/target/classes/META-INF/aop.xml 
[WeavingURLClassLoaderHelper] info register aspect org.intellimate.izou.security.replaced.MixerAspect 
[WeavingURLClassLoaderHelper] info AspectJ Weaver Version 1.8.5 built on Thursday Jan 29, 2015 at 01:03:58 GMT 
[WeavingURLClassLoaderHelper] info register classloader ro.fortsoft.pf4j.IzouPluginClassLoader$WeavingURLClassLoaderHelper 
[WeavingURLClassLoaderHelper] info using configuration /Users/LeanderK/IdeaProjects/Izou/target/classes/META-INF/aop.xml 
[WeavingURLClassLoaderHelper] info register aspect org.intellimate.izou.security.replaced.MixerAspect 
...(no relevant log) 
[WeavingURLClassLoaderHelper] debug weaving 'javax.sound.sampled.AudioSystem' 
[WeavingURLClassLoaderHelper] weaveinfo Join point 'method-execution(javax.sound.sampled.Line javax.sound.sampled.AudioSystem.getLine(javax.sound.sampled.Line$Info))' in Type 'javax.sound.sampled.AudioSystem' (AudioSystem.java:410) advised by around advice from 'org.intellimate.izou.security.replaced.MixerAspect' (MixerAspect.class(from MixerAspect.java)) 
[WeavingURLClassLoaderHelper] debug generating class 'javax.sound.sampled.AudioSystem$AjcClosure1' 
2015-05-24 20:12:13,945 FATAL [Thread-5] org.intellimate.izou.threadpool.ThreadPoolManager (ThreadPoolManager.java:59) - unable to provide callback for: org.intellimate.izou.addon.AddOnManager$$Lambda$19/[email protected] 
java.util.concurrent.CompletionException: java.lang.NoSuchMethodError: org.intellimate.izou.security.replaced.MixerAspect.aspectOf()Lorg/intellimate/izou/security/replaced/MixerAspect; 
    at java.util.concurrent.CompletableFuture.internalComplete(CompletableFuture.java:205) [?:1.8.0_25] 
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:459) [?:1.8.0_25] 
    at java.util.concurrent.CompletableFuture$Async.run(CompletableFuture.java:428) [?:1.8.0_25] 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_25] 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_25] 
    at org.intellimate.izou.threadpool.ThreadPoolManager$LoggingThreadFactory$1.run(ThreadPoolManager.java:73) [classes/:?] 
Caused by: java.lang.NoSuchMethodError: org.intellimate.izou.security.replaced.MixerAspect.aspectOf()Lorg/intellimate/izou/security/replaced/MixerAspect; 
    at javax.sound.sampled.AudioSystem.getLine(AudioSystem.java:410) ~[?:1.8.0_25] 
    at leanderk.izou.playground.ExampleAddOn.prepare(ExampleAddOn.java:41) ~[?:?] 
    at org.intellimate.izou.sdk.addon.AddOn.register(AddOn.java:41) ~[?:?] 
    at org.intellimate.izou.addon.AddOnManager$$Lambda$19/970865974.run(Unknown Source) ~[?:?] 
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:454) ~[?:1.8.0_25] 
    ... 4 more 

, похоже, это не ткут, а почему? Я не знаю, что еще попробовать. У меня есть следующие зависимости:

<dependency> 
    <groupId>org.aspectj</groupId> 
    <artifactId>aspectjweaver</artifactId> 
    <version>1.8.5</version> 
</dependency> 
<dependency> 
    <groupId>aspectj</groupId> 
    <artifactId>aspectjrt</artifactId> 
    <version>1.5.4</version> 
</dependency> 

, чтобы еще более усложнить вещи, загрузчик классов в другом проекте с простым Maven зависимости для этого проекта. Есть ли какой-то aspectj-intitialization, которого я не хватает?


редактировать уточнить ответ: вы также должны определить аспект через WeavingURLClassloader, это мой (пример - его упрощенный) код, то же самое может быть применен для каждого класса, который вы хотите смешивать-в. В моем случае класс был уже загружен через систему-загрузчик, так что я должен был excplicitly позвонить определить (быть осторожными, одни и те же классы, загруженные из различных загрузчиков классов не то же самые!)

private Class mixer = null; 
...... 
@Override 
public Class<?> loadClass(String className) throws ClassNotFoundException { 
    ..... 
    else if (className.contains("MixerAspect")) { 
     InputStream is = this.getResourceAsStream(className.replace('.', '/') + ".class"); 
     ByteArrayOutputStream buffer = new ByteArrayOutputStream(); 

     int nRead; 
     byte[] data = new byte[16384]; 

     try { 
      while ((nRead = is.read(data, 0, data.length)) != -1) { 
       buffer.write(data, 0, nRead); 
      } 
     } catch (IOException e) { 
      throw new ClassNotFoundException("unable to load class", e); 
     } 

     try { 
      buffer.flush(); 
     } catch (IOException e) { 
      throw new ClassNotFoundException("unable to load class", e); 
     } 
     byte[] array = buffer.toByteArray(); 
     URL mixerAspect = getResource("org/intellimate/izou/security/replaced/MixerAspect.class"); 
     try { 
      if (mixer == null) { 
       mixer = weaver.defineClass(className, array, new CodeSource(mixerAspect, (Certificate[]) null)); 
      } 
      return mixer; 
     } catch (IOException e) { 
      throw new ClassNotFoundException("unable to define class", e); 
     } 
    } 

ответ

2

При использовании стиля аннотаций аспекты и компиляция с помощью javac вам нужно, чтобы аспект был «завершен» при загрузке с прохождением через самого ткача. Если вы этого не сделаете, он не сможет генерировать вспомогательные методы, такие как aspectOf(), которые будут вызываться из других типов плетения, пытающихся использовать аспект. NoSuchMethodError для aspectOf() говорит мне, что аспект не сплетен. Тот факт, что aspectOf() вызывает вообще, говорит мне, что другие типы сплетены успешно. Пара вариантов:

  • использование AJC скомпилировать MixerAspect, это добавит дополнительные методы во время компиляции

  • обеспечить ваш процесс ткачества позволяет MixerAspect быть соткана. Убедитесь, что он загружен с использованием других классов, а не родительского загрузчика? Или позволить родительскому загрузчику тоже переплетать?

+0

Я делаю 100% -ное время переплетения времени ... так происходит какое-то преобразование. Я не знаю, понимаю ли я это правильно ... если я переплетаю javax.sound.sampled.AudioSystem, делает org.intellimate.izou.security.replaced.MixerAspect меняет? – Leander

+0

No MixerAspect не изменяется во время плетения любого * конкретного * типа, но недостаточно просто скомпилировать MixerAspect с javac, он должен пройти через ткача, чтобы получить добавленные методы поддержки. Если он не получит aspectOf(), то ни один рекомендуемый класс не сможет с ним поговорить. Как я уже сказал, вам либо нужно использовать ajc для создания MixerAspect, либо вам нужно передать его через ткача с другими вашими типами. Как только MixerAspect был дополнен ткачом (один раз), его можно использовать с любым другим тканым типом, все они будут называть aspectOf(). –

+0

ОК, спасибо ... его работа! :) – Leander

1

Да, я выбрал второй, и он работал в LTW.

<!DOCTYPE aspectj PUBLIC 
     "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> 
<aspectj> 
    <weaver> 
     <!--<weaver options="-verbose -showWeaveInfo -debug">--> 
     <include within="com.rabbitmq.client.impl.ChannelN"/> 
     <include within="**.MQAspect"/> 
    </weaver> 
    <aspects> 
     <!-- weave in just this aspect --> 
     <aspect name="**.MQAspect"/> 
    </aspects> 
</aspectj> 
Смежные вопросы