fetching running bytecode from a JVM

喜夏-厌秋 提交于 2021-02-08 03:10:32

问题


I am trying to find out if it is possible to get the bytecode of a function after it was loaded to the JVM.

I know I can get the code from the .class file using ClassLoder and I can manipulate it using Instrumentation, but this is not the issue here.

Suppose I have a compiled Java program called Test.class and I run, its bytecode will be loaded the JVM, from this point can I get the bytecode?

EDIT: Following the answers I want to point again, my intention is to inspect code which is running on the JVM but I dont have access to its compiled file.


回答1:


Without more context I'm not sure what you're trying to do, but:

If you just want to see the contents of a class file (bytecodes and all), then javap -c Test.class will spit it out for you.

If you want to see what the code looks like while a JVM is running, an agent might be what you're looking for.

Remember that if your function (method? I'm assuming we're not talking about lambdas here) relies on any variables from the parent scope then the bytecode for said method doesn't describe what it does on its own. Think of inner classes, lambdas, e.t.c.

Edit:

As Peter Lawrey said, if you want to forgo agents, feeding the raw bytes from a class loader into ASM's visitor API is a good start. The ASM doc has a tutorial; Google also turned up this (see part 2). HTH




回答2:


HotSpot Serviceability Agent can do this!

Here is an example how to get the bytecode of remote main(String[]) method in test.HelloWorld class:

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 GetBytecode extends Tool {

    @Override
    public void run() {
        VM.getVM().getSystemDictionary().allClassesDo(klass -> {
            if (klass.getName().asString().equals("test/HelloWorld")) {
                Method method = ((InstanceKlass) klass).findMethod("main", "([Ljava/lang/String;)V");
                for (byte bc : method.getByteCode()) {
                    System.out.printf("%02x ", bc);
                }
            }
        });
    }

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

Run java -cp <JDK_HOME>/lib/sa-jdi.jar:. GetBytecode <PID>



来源:https://stackoverflow.com/questions/32127088/fetching-running-bytecode-from-a-jvm

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!