AspectJ AOP LTW无法动态加载javaagent [英] AspectJ AOP LTW not working with dynamic loading of javaagent

查看:155
本文介绍了AspectJ AOP LTW无法动态加载javaagent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的非工作项目样本

它包含2个模块:


  • aop-lib - 用作lib的方面。它包含以下类

  • aop-lib - Aspects used as lib. It contains the following classes

  1. Wrap.java - 这是用于附加建议的注释

  2. WrapDef.java - 这是上面提到的 Wrap 注释的定义。

  1. Wrap.java - It's the annotation used to attach advice
  2. WrapDef.java - It is the definition of the above mentioned Wrap annotation.


  • aop-app - 使用上述方面lib

  • aop-app - Uses the above aspect lib


    1. DynamicLoad.java - 动态加载javaagent的类

    2. Main.java - 使用 Wrap 的主类注释。

    1. DynamicLoad.java - class to load javaagent dynamically
    2. Main.java - Main class which uses Wrap annotation.


  • 目录结构如下:

    .
    ├── README.md
    ├── aop-app
    │   ├── pom.xml
    │   └── src
    │       └── main
    │           └── java
    │               └── com
    │                   └── aop
    │                       └── app
    │                           ├── DynamicLoad.java
    │                           └── Main.java
    └── aop-lib
        ├── pom.xml
        └── src
            └── main
                └── java
                    └── com
                        └── aop
                            └── app
                                └── lib
                                    ├── Wrap.java
                                    └── WrapDef.java
    

    我正在尝试使用方面lib aop-lib (一个AOP建议库) aop-app thro通过动态加载javaagent来加载时间编织(LTW),如中所述官方文档。但它不起作用。

    I'm trying to use the aspect lib aop-lib (an AOP advice lib) inside aop-app through Load Time Weaving (LTW) by dynamically loading the javaagent as mentioned in the official docs. But it's not working.

    以下是 Wrap.java

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(value = RetentionPolicy.RUNTIME)
    public @interface Wrap { }
    

    以下是 WrapDef.java

    @Aspect
    public class WrapDef {
        private static final Logger logger = LoggerFactory.getLogger(WrapDef.class);
    
        public static boolean loaded = false;
    
        @Around("@annotation( wrapAnnotation ) && execution(* *(..))")
        public Object processSystemRequest(final ProceedingJoinPoint pjp, Wrap wrapAnnotation)
                throws Throwable {
            logger.debug("before wrap");
            Object o = pjp.proceed();
            logger.debug("after wrap");
            return o;
        }
    
        static {
            System.out.println("Loading");
            WrapDef.loaded = true;
        }
        public static void reportLoaded() {
            System.out.println("loaded : " + loaded);
        }
    }
    

    以下是 Main.java

    public class Main {
    
        private static final Logger logger = LoggerFactory.getLogger(Main.class);
    
        @Wrap
        public void myFunc(){
            logger.debug("inside myFunc");
        }
    
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    
            boolean dynamicLoad = Boolean.getBoolean("dynamicLoad");
            if(dynamicLoad){
                Main.isAdviceClassLoaded();           //To see if WrapDef.java is loaded or not.
                if(!DynamicLoad.isAspectJAgentLoaded()) {
                    logger.error("AspectJ Not Loaded. Existing.");
                    System.exit(0);
                }
                Main.isAdviceClassLoaded();           //To see if WrapDef.java is loaded or not.
            }
    
            new Main().myFunc();
        }
    
        private static void isAdviceClassLoaded() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
            m.setAccessible(true);
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            Object test1 = m.invoke(cl, "com.aop.app.lib.WrapDef");
            boolean loaded = test1 != null;
            System.out.println("com.aop.app.lib.WrapDef Loaded : " + loaded);
        }
    
    }
    

    javaagent 作为cmd行arg,它运行得很好:

    With javaagent as cmd line arg, it works perfectly fine:

    $ java -javaagent:deploy/lib/aspectjweaver-1.9.1.jar -classpath aop-app-1.0.jar:deploy/lib/* com.aop.app.Main
    14:02:45.384 [main] DEBUG com.aop.app.lib.WrapDef - before wrap
    14:02:45.391 [main] DEBUG com.aop.app.Main - inside myFunc
    14:02:45.391 [main] DEBUG com.aop.app.lib.WrapDef - after wrap
    

    但是,动态加载 javaagent ,它给出以下输出:

    But, with Dynamic loading of javaagent, it gives the following output:

    $ java -DdynamicLoad=true -DAGENT_PATH=deploy/lib/aspectjweaver-1.9.1.jar -classpath aop-app-1.0.jar:deploy/lib/* com.aop.app.Main
    com.aop.app.lib.WrapDef Loaded : false                   //The WrapDef is NOT loaded before JAVAAGENT is Loaded - which is correct
    java.lang.UnsupportedOperationException: AspectJ weaving agent was neither started via '-javaagent' (preMain) nor attached via 'VirtualMachine.loadAgent' (agentMain)
    loading javaAgent deploy/lib/aspectjweaver-1.9.1.jar
    loaded javaAgent deploy/lib/aspectjweaver-1.9.1.jar      //The JAVAAGENT is Dynamically Loaded - which is correct
    com.aop.app.lib.WrapDef Loaded : false                   //The WrapDef is STILL NOT loaded even AFTER JAVAAGENT is Loaded - THIS IS THE ISSUE
    15:53:08.543 [main] DEBUG com.aop.app.Main - inside myFunc
    

    官方文档确实说在附件之前加载的任何类都不会被编织。但是,正如您在上面的输出中所看到的那样,根本没有加载 WrapDef 类。

    The official docs does say that any classes loaded before attachment will not be woven. But, on the contrary as you can see in the above output, the WrapDef class is not loaded at all.

    另外,请注意我在 aspectj-maven-plugin master / aop-lib / pom.xmlrel =nofollow noreferrer> aop-lib / pom.xml ,包含以下选项:

    Also, note that I'm using aspectj-maven-plugin in my aop-lib/pom.xml, with the following options:

    <outxml>true</outxml>                           //creates META-INF/aop-ajc.xml
    <showWeaveInfo>true</showWeaveInfo>             //supposed to create <weaver options="-showWeaveInfo"/> BUT DOES NOT WORK
    <verbose>true</verbose>                         //supposed to create <weaver options="-verbose"/> BUT DOES NOT WORK
    

    因此,它会创建 META-INF / aop-ajc .xml aop-lib-1.0.jar 内,内容如下:

    So, it creates META-INF/aop-ajc.xml inside aop-lib-1.0.jar with the following content:

    <aspectj>
    <aspects>
    <aspect name="com.aop.app.lib.WrapDef"/>
    </aspects>
    </aspectj>
    

    但其他标签对应 showWeaveInfo & ; verbose 未在 META-INF / aop-ajc.xml 中创建。这是另一件在这里不起作用的事情。

    but the other tags corresponding to showWeaveInfo & verbose are not created in META-INF/aop-ajc.xml. This is another thing that is not working here.

    如果您需要任何其他信息 - 我将提供它。

    If you require any other info - I shall provide it.

    感谢任何帮助。

    推荐答案

    解释非常简单:您正在类<$ c中直接测试编织代理$ c>主已经加载之前您从该类附加了该代理。因此,您必须避免过早加载您喜欢编织的类。我建议你把方法 myFunc()(可怕的名字,顺便说一句)放到另一个类中。怎么样?

    The explanation is quite simple: You are testing the weaving agent directly in class Main which is already loaded before you attach that very agent from that class. So you have to avoid classes which you like to be woven to be loaded too early. I suggest you put method myFunc() (horrible name, by the way) into another class. How about that?

    package com.aop.app;
    
    import com.aop.app.lib.Wrap;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class Application {
      private static final Logger logger = LoggerFactory.getLogger(Application.class);
    
      @Wrap
      public void myFunc(){
        logger.debug("inside myFunc");
      }
    
      public static void main(String[] args) {
        new Application().myFunc();
      }
    }
    

    然后在 Main.main(..)你启动你想要编织的实际应用程序:

    Then in the last line of Main.main(..) you start the actual application you want woven:

    Application.main(null);
    

    这将产生以下输出:

    com.aop.app.lib.WrapDef Loaded : false
    java.lang.UnsupportedOperationException: AspectJ weaving agent was neither started via '-javaagent' (preMain) nor attached via 'VirtualMachine.loadAgent' (agentMain)
    loading javaAgent aop-app/target/deploy/lib/aspectjweaver-1.9.1.jar
    loaded javaAgent aop-app/target/deploy/lib/aspectjweaver-1.9.1.jar
    com.aop.app.lib.WrapDef Loaded : false
    Loading
    07:56:21.703 [main] DEBUG com.aop.app.lib.WrapDef - before wrap
    07:56:21.716 [main] DEBUG com.aop.app.Application - inside myFunc
    07:56:21.716 [main] DEBUG com.aop.app.lib.WrapDef - after wrap
    

    PS:你真的认为方面库的用户更容易指定JVM命令行上的两个属性,而不是仅使用 -javaagent:/path/to/aspectweaver.jar ?无论如何,您可能有理由使用动态编织器附件。在某种程度上,我很高兴有人使用我刚才添加到AspectJ的功能。 ; - )

    P.S.: Do you really think it is easier for users of your aspect library to specify two properties on the JVM command line instead of just using -javaagent:/path/to/aspectweaver.jar? Anyway, you probably have your reasons to use dynamic weaver attachment. In a way I am kind of happy that someone uses the functionality I added to AspectJ myself a while ago. ;-)

    这篇关于AspectJ AOP LTW无法动态加载javaagent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆