当前位置: 首页 > 面试题库 >

AspectJ AOP LTW无法与javaagent的动态加载一起使用

敖和韵
2023-03-14
问题内容

这是我的示例无效项目。

它包含2个模块:

  • aop- lib-用作lib的方面。它包含以下类
    1. Wrap.java- 这是用于附加建议的注释
    2. WrapDef.java- 这是上述Wrap注释的定义。
  • aop-app- 使用上述方面的lib
    1. DynamicLoad.java- 用于动态加载javaagent的类
    2. Main.java- 使用Wrap注释的主类。

目录结构如下:

.
├── 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

我正在尝试通过如官方文档中所述动态加载javaagent来通过Load
Time Weaving(LTW)aop-lib在内部使用方面lib (AOP建议库)。但这不起作用。aop- app

以下是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);
    }

}

使用javaagentcmd行arg,它可以正常工作:

$ 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,它会提供以下输出:

$ 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 html" target="_blank">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

在官方的文档没有说any classes loaded before attachment will not be woven。但是,相反,如您在上面的输出中看到的,WrapDef该类根本没有加载。

另外,请注意,我aspectj-maven-plugin在aop-lib /
pom.xml
中使用以下选项:

<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

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

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

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

任何帮助表示赞赏。


问题答案:

解释很简单:你直接在课堂上测试织造剂Main,其已被加载 之前
你从该类附上极剂。因此,您必须避免将要编织的类过早加载。我建议您将方法myFunc()(很糟糕的名称)放入另一个类。那个怎么样?

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(..),启动您要编织的实际应用程序:

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吗?无论如何,您可能有使用动态Weaver附件的理由。从某种程度上来说,我很高兴有人使用我自己不久前添加到AspectJ中的功能。;-)



 类似资料:
  • 我有高塞拉操作系统-版本10.13.6 PHP版本:PHP 7.1.9 当我尝试做命令总是出现这样的错误: PHP启动:无法加载动态库'/usr/本地/php5-7.1.9-20170914-100859 /lib/php/extensions/no-debug-non-zts-20160303/imagick.so'-dlopens(/usr/本地/php5-7.1.9-20170914-100

  • 我有64位Windows 7、IIS 7,并在IIS上安装了PHP。我启用了php_oci8。用于Oracle连接的dll,但出现以下错误: 我已经检查了php_oci8。dll存在于:“C:\Program Files(x86)\PHP\v5”中。5\ext\php\u oci8。dll' 我的php。见下: 我在http://www.oracle.com/technetwork/topics/

  • 问题内容: 我是初学者。我正在尝试在php上安装mongodb驱动程序。 请按照此处的说明进行操作:http : //php.net/manual/zh/mongo.installation.php#mongo.installation.windows 我已经用VC11尝试了所有php_mongo.dll文件,并将其放在php / ext文件夹中。并添加到php.ini文件中,但是当我尝试在xam

  • 问题内容: 我的程序应该等待按下向左或向右箭头键,然后更改一个值,以便下次更新PaintComponent时,屏幕看起来有所不同。但是,运行该程序时,屏幕没有变化。 以下是变量声明: 这是主要的KeyListener声明: 这是用于绘画的方法: 当我运行该程序时,该程序会打印外壳,但是当我按箭头键时,屏幕上没有任何变化。 问题答案: 您需要先将关键侦听器添加到组件,然后才能调用它: 您还需要使组件

  • 问题内容: click事件可以正常运行,但是onmouseover事件不起作用。 问题答案: 您需要大写一些字母。

  • 问题内容: 我有这个规格 使用此页面定义 我需要像上面一样动态配置属性:SEE 问题答案: 据我所知,这并不存在。该批注采用静态而已。您可能需要自定义修改注释处理器,类似于此博客的行为:https ://web.archive.org/web/20180612042724/http: //brimllc.com/2011/01/selenium-2-0-webdriver-扩展查找以支持动态idx