2015-05-23 43 views
0

注意:這是一個概念實現的證明,而不是最終的東西。NoSuchMethodError與AspectJ

我有第三。第三方添加,我想限制他們對聲音的使用,例如限制持續時間等(安全管理員不可能)。爲了實現這一點,我想用wrapper替換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); 
     } 

這是WeavingURLClassloader的initlialization代碼:

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

父是類加載器能夠訪問混合機方面和方面是URL陣列僅元素是一個指出到t他所在的目錄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> 

事情進一步複雜化,類加載器是在另一個項目,是一個簡單的行家依賴於這個項目。 我缺少一些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()這樣的幫助器方法,這些幫助器方法將從試圖使用該方面的其他編織類型中調用。 NoSuchMethodErroraspectOf()告訴我方面沒有編織。被稱爲aspectOf()的事實告訴我,其他類型正在成功編織。的選擇情侶:

  • 使用濃縮蘋果汁來編譯MixerAspect,這將在編譯時

  • 添加額外的方法,確保您的編織工藝讓MixerAspect編織。確保它裝載的是正在編織的其他類而不是父裝載器?還是讓父裝載機也編織呢?

+0

我在做100%的加載時間編織......所以發生了某種轉換。我不知道我是否理解正確...如果我編織javax.sound.sampled.AudioSystem,org.intellimate.izou.security.replaced.MixerAspect是否更改? – Leander

+0

在編織任何*特殊*類型期間,沒有MixerAspect不會改變,但僅僅用javac編譯MixerAspect是不夠的,它必須通過編織器才能添加支持方法。如果它沒有得到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>