是否曾经在运行中的JVM中调用过此方法

时间:2019-04-15 22:33:41

标签: java jvm coredump

是否有办法确定在运行的JVM中是否曾经调用过某个方法。假设我有以下方法信息,并且想知道它是否曾经被调用过:

const getTotalResponses = () => {
const result = {
// This holds actual total outboxes
             totalOutboxes,
             conversations
        }
        return result;
    };

1 个答案:

答案 0 :(得分:3)

如果应用程序在HotSpot JVM上运行,则可以使用HotSpot Serviceability Agent获取有关给定方法的信息。

这是一个检查该方法是否已在运行的JVM中被调用的工具。

import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.Method;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;

public class CheckMethodCall extends Tool {
    private static final String className = "java/util/HashMap";
    private static final String methodName = "get";
    private static final String methodSig = "(Ljava/lang/Object;)Ljava/lang/Object;";

    @Override
    public void run() {
        boolean[] result = new boolean[2];

        VM.getVM().getSystemDictionary().classesDo(klass -> {
            if (klass.getName().asString().equals(className)) {
                Method method = ((InstanceKlass) klass).findMethod(methodName, methodSig);
                if (method != null) {
                    result[0] = true;
                    result[1] = method.getMethodCounters() != null &&
                        method.getInvocationCount() + method.interpreterInvocationCount() > 0;
                }
            }
        });

        if (!result[0]) {
            System.out.println("Method not found");
        } else if (result[1]) {
            System.out.println("Method has been called");
        } else {
            System.out.println("Method has NOT been called");
        }
    }

    public static void main(String[] args) {
        new CheckMethodCall().execute(args);
    }
}

它在类路径中需要sa-jdi.jar(JDK 8附带)。

运行

java -cp $JAVA_HOME/lib/sa-jdi.jar:. CheckMethodCall <pid>

其中<pid>是要检查的Java进程ID。

更新

JDK 11+的类似工具
使用--add-modules=jdk.hotspot.agent并导出所有必需的软件包。

import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.oops.Method;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.tools.Tool;

public class CheckMethodCall extends Tool {
    private static final String className = "java/util/HashMap";
    private static final String methodName = "get";
    private static final String methodSig = "(Ljava/lang/Object;)Ljava/lang/Object;";

    @Override
    public void run() {
        Klass klass = VM.getVM().getClassLoaderDataGraph().find(className);
        if (klass == null) {
            System.out.println("Class not found");
            return;
        }

        Method method = ((InstanceKlass) klass).findMethod(methodName, methodSig);
        if (method == null) {
            System.out.println("Method not found");
            return;
        }

        boolean called = method.getMethodCounters() != null &&
                method.getInvocationCount() + method.interpreterInvocationCount() > 0;
        System.out.println("Method " + (called ? "has been" : "has NOT been") + " called");
    }

    public static void main(String[] args) {
        new CheckMethodCall().execute(args);
    }
}