检查是否加载了 aspectjweaver(或任何 javaagent)

Check if aspectjweaver (or any javaagent) is loaded

是否有(首选便携式)方法来检查是否 JVM 已用特定的 -javaagent?

声明

我特别想知道 aspectj 加载时间编织器是否已加载。 (我试图在启动不正确的情况下提供有用的错误消息)。

以下代码显示

  • 一种确定任何 -javaagent:... JVM 参数的方法,
  • 一种检查 AspectJ 编织代理入口点的方法 class(aspectjweaver.jar 的清单条目 Premain-Class: 中提到的那个) 已加载。

前者只是证明参数是在命令行给出的,并不是真正找到并启动了代理。

后者只是证明编织器在class路径上可用,并不是说它真的是作为代理启动的。两者的结合应该让您非常有信心代理实际上是活跃的。

package de.scrum_master.app;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;

public class Application {
    public static void main(String[] args) {
        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
        List<String> arguments = runtimeMxBean.getInputArguments();
        for (String argument : arguments) {
            if (argument.startsWith("-javaagent:"))
                System.out.println(argument);
        }
        try {
            Class.forName("org.aspectj.weaver.loadtime.Agent");
        } catch (ClassNotFoundException e) {
            System.err.println("WARNING: AspectJ weaving agent not loaded");
        }
    }
}

您可能还会发现问题 Starting a Java agent after program start 及其部分答案很有帮助。


更新:

好的,这是我自己的解决方案和你的解决方案的组合,但即使编织器不可用,该解决方案也能正常工作,这很重要,因为这是您首先要检查的内容:

public static boolean isAspectJAgentLoaded() {
    try {
        Class<?> agentClass = Class.forName("org.aspectj.weaver.loadtime.Agent");
        Method method = agentClass.getMethod("getInstrumentation");
        method.invoke(null);
    } catch (Exception e) {
        //System.out.println(e);
        return false;
    }
    return true;
}

更新二:

在与 OP bacar 讨论后,我决定提供一个不使用反射但捕获 NoClassDefError 的解决方案:

public static boolean isAspectJAgentLoaded() {
    try {
        org.aspectj.weaver.loadtime.Agent.getInstrumentation();
    } catch (NoClassDefFoundError | UnsupportedOperationException e) {
        System.out.println(e);
        return false;
    }
    return true;
}

现在两种主要错误类型

  • 编织代理在 class 路径上可用,但检测尚未启动,因为 aspectjweaver.jar 未作为 Java 启动经纪人,
  • 代理 aspectjweaver.jar 根本不在 class 路径上,因此 class org.aspectj.weaver.loadtime.Agent 不可用

通过返回 false after 警告消息(在这个简单的示例中只是清楚说明错误的异常)已打印在控制台上,从而得到妥善处理。

这两种情况可能的控制台输出是:

  • java.lang.UnsupportedOperationException: Java 5 was not started with preMain -javaagent for AspectJ
  • java.lang.NoClassDefFoundError: org/aspectj/weaver/loadtime/Agent

我发现了以下作品(针对 1.8.4 进行了测试),尽管 它依赖于未记录的 aspectjweaver 功能,因此可能无法跨版本工作。

public static boolean isAspectJAgentLoaded() {
    try {
        org.aspectj.weaver.loadtime.Agent.getInstrumentation();
        return true;
    } catch (UnsupportedOperationException e) { 
        return false;
    }
}

解释:当aspectj作为代理加载时,org.aspectj.weaver.loadtime.Agent.premain(...)静态方法被JVM调用。这有一个我们可以测试的副作用。调用 getInstrumentation 要么抛出 UnsupportedOperationException(如果它没有初始化为代理),要么抛出 returns 成功。