有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

是否有(pref-portable)方法检查 JVM已经用一个特定的-javaagent来声明了

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


共 (2) 个答案

  1. # 1 楼答案

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

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

    说明:当aspectj作为代理加载时,JVM会调用^{}静态方法。这有一个副作用,我们可以测试。调用getInstrumentation要么抛出UnsupportedOperationException(如果它没有初始化为代理),要么成功返回

  2. # 2 楼答案

    下面的代码显示

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

    前者只是证明了参数是在命令行上给出的,而不是代理实际上是被找到并启动的

    后者只是证明weaver在类路径上可用,而不是它实际上是作为代理启动的。两者的结合应该会让你非常确信这个代理实际上是活跃的

    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;
    }
    

    更新2:

    在与OPbacar讨论之后,我决定提供一种解决方案,它不使用反射,而是捕捉NoClassDefError

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

    现在两种主要的错误类型

    • 编织代理在类路径上可用,但由于aspectjweaver,检测尚未启动。jar不是作为Java代理启动的
    • 代理aspectjweaver。jar根本不在类路径上,因此类org.aspectj.weaver.loadtime.Agent不可用

    在控制台上打印了false警告消息(在这个简单的示例中,只有清楚地说明了错误的异常)之后,通过返回false来优雅地处理

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

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