【问题标题】:Load time weaving of javax.swing.* classes with AspectJ使用 AspectJ 对 javax.swing.* 类进行加载时编织
【发布时间】:2012-02-10 21:28:16
【问题描述】:

我正在使用 AspectJ 来跟踪对图形类的调用。 到目前为止,我已经使用了一组预先编织的 javax.swing.* 类,并在加载时告诉 JVM 使用这些编织的类,而不是使用 -Xbootclasspath/p 开关来自 JRE 的类。

我想切换到加载时间编织模式。 任何人都可以帮助我如何在加载时间编织 javax.swing。我已经搜索了网络,但我仍然无法弄清楚如何去做。我知道默认情况下,AspectJ 加载时间编织器不会编织 java.* 和 javax.* 类。有人建议使用

-Xset:weaveJavaPackages=true,weaveJavaxPackages=true

在 aop.xml 中,但这些都没有帮助,因为 javax.swing 类是在 weaver 连接到类加载器之前加载的。我猜编织者根本看不到这些类。

如何管理动态编织 javax.swing 类?我应该实现一个自定义类加载器,首先注册一个编织器然后加载类吗?

有人可以提出任何解决方案吗?

【问题讨论】:

  • 我没有给你一个好的答案,只是因为你说的原因,编织 java 和 javax 类非常棘手(它们是在加载编织器之前加载的。自定义类加载器可能帮助,但不能保证。如果可能的话,我会坚持编译时间编织。
  • 确实,在加载时间 java 引导类上似乎很难编织。我听说有些人为此实现使用了自定义编织器,但没有人分享任何关于如何做到这一点的规范。
  • 我同意上述 cmets 的观点,即这将很难做到。也许如果您告诉我们您为什么要这样做(即您的真正问题是什么),我们可以为您提供编织之外的替代方案。
  • 正如 Adrew 所说,这很棘手,因为这是一个母鸡与鸡蛋的问题:您需要先加载运行时环境,然后才能运行任何 Java 程序(例如编织代理),但是您需要编织代理来检测一些 JDK/JRE 类。如果您发布一些示例代码 - 最好是 SSCCE - 我想研究一下并尝试一下。

标签: swing aspectj java


【解决方案1】:

如果您需要对javax 包使用execution() 切入点,我可以建议的唯一解决方案是二进制编织JRE 的tools.jar 并创建您自己的编织版本。我过去做过,效果很好。但是,如果您可以控制运行应用程序的运行时环境,这只是一种选择。

如果您不想使用这种方法,则必须求助于call() 切入点。通过这种方式,您可以捕获由您自己的应用程序或任何受 LTW 影响的第三方库发出的调用。只有由引导类加载器加载的 JRE 类进行的调用才会逃脱您的方面,这应该不会太糟糕。

【讨论】:

    【解决方案2】:

    我绝不是专家,但虽然这看起来很有希望:

    Configuring Load-time Weaving with aop.xml files

    具体来说:

    <aspectj>
      <aspects>
        ...
      </aspects>
      <weaver options="-verbose">
        <!-- 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.aspectj.*"/>
        <include within="(!@NoWeave foo.*) AND foo.*"/>
        ... 
      </weaver>
    </aspectj>
    

    鉴于 LTW 代理使用的ClassPreProcessor,我不确定它是如何工作的(尽管我还没有尝试过)。这是它的preProcess 方法的开头:

    public byte[] preProcess(String className, byte[] bytes, ClassLoader loader, ProtectionDomain protectionDomain) {
        if (loader == null || className == null || loader.getClass().getName().equals(deleLoader)) {
            // skip boot loader, null classes (hibernate), or those from a reflection loader
            return bytes;
        }
        ...
        try {
            synchronized (loader) {
                ...
                WeavingAdaptor weavingAdaptor = WeaverContainer.getWeaver(loader, weavingContext);
                ...
            }
        }
    }
    

    这清楚地说明了如何跳过引导加载程序类。此外,WeaverContainer.getWeaver() 调用似乎触发了aop.xml 处理,并且直到处理具有非空加载器的类之后才会发生。

    不确定这对实际解决方案有多大帮助,但希望它能阐明为什么事情会如此行事......

    【讨论】:

      【解决方案3】:

      你已经成功了一半 它并不难,相当简单。

      <?xml version="1.0" encoding="UTF-8"?>
       <aspectj>
        <aspects>
       <aspect name="com.ciena.EDTCheck"/>
       </aspects>
          <weaver options="-Xset:weaveJavaxPackages=true -verbose">    
          </weaver>
        </aspectj>
      

      确保你有

      javaagent 中的aspectjweaver.jar 比如-javaagent:C:\aspectj1.8\lib\aspectjweaver.jar

      还要确保上面的 aop.xml 位于 META-INF 文件夹中

      这一切都可以从 Eclipse 或某些 IDE 中运行

      如果你想从命令行运行,请确保你也给了 -javagaent

      【讨论】:

      • 您是否真正尝试过,它对您有用吗?对我来说不是。
      猜你喜欢
      • 1970-01-01
      • 2014-11-01
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      相关资源
      最近更新 更多