是否曾经在运行中的JVM中调用过此方法 [英] Has this method ever been called inside a running JVM

查看:81
本文介绍了是否曾经在运行中的JVM中调用过此方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a way to figure out if a method ever been called inside running JVM. Let's say I have the following method information and I want to know if it has ever been called:

    "methodId": {
      "className": "InvokerParser",
      "filePath": "org/foo/commons/functors/InvokerParserformer.java",
      "methodName": "parser"
    }

推荐答案

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

If the application is running on HotSpot JVM, it is possible to get the information about the given method using HotSpot Serviceability Agent.

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

Here is a tool that checks whether the method has been called in a running 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附带).

It requires sa-jdi.jar in classpath (comes with JDK 8).

运行

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

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

where <pid> is Java process ID to check.

更新

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

A similar tool for JDK 11+
Use --add-modules=jdk.hotspot.agent and export all the required packages.

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

这篇关于是否曾经在运行中的JVM中调用过此方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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