Created
January 31, 2016 19:16
-
-
Save apangin/781683bc86ab19e92372 to your computer and use it in GitHub Desktop.
Using JVMTI to obtain bytecodes of a Java method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <jvmti.h> | |
static jvmtiEnv* jvmti; | |
JNIEXPORT jint JNICALL | |
JNI_OnLoad(JavaVM* vm, void* reserved) { | |
(*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0); | |
jvmtiCapabilities capabilities = {0}; | |
capabilities.can_get_bytecodes = 1; | |
capabilities.can_get_constant_pool = 1; | |
jvmtiError err = (*jvmti)->AddCapabilities(jvmti, &capabilities); | |
return JNI_VERSION_1_4; | |
} | |
JNIEXPORT jbyteArray JNICALL | |
Java_Bytecodes_getBytecodes(JNIEnv* env, jclass cls, jobject method) { | |
jmethodID methodID = (*env)->FromReflectedMethod(env, method); | |
jint bytecode_size; | |
unsigned char* bytecodes; | |
if ((*jvmti)->GetBytecodes(jvmti, methodID, &bytecode_size, &bytecodes) != 0) { | |
return NULL; | |
} | |
jbyteArray result = (*env)->NewByteArray(env, bytecode_size); | |
if (result != NULL) { | |
(*env)->SetByteArrayRegion(env, result, 0, bytecode_size, bytecodes); | |
} | |
(*jvmti)->Deallocate(jvmti, bytecodes); | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Method; | |
import java.util.Arrays; | |
public class Bytecodes { | |
static { | |
System.loadLibrary("bytecodes"); | |
} | |
private static native byte[] getBytecodes(Method method); | |
public static void main(String[] args) throws Exception { | |
Method m = Object.class.getDeclaredMethod("toString"); | |
byte[] bytecode = getBytecodes(m); | |
System.out.println(Arrays.toString(bytecode)); | |
} | |
} |
Shouldn't it be also possible with the JvmtiClassFileReconstituter
? As I understand, instrumentation's retransform
method collects class' bytecode via this reconstituter (if it's not cached). Not sure if it's portable though :D
But since we are already doing something dirty, why not skip the middle man (agent)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Yes, using RetransformClasses API.
See https://github.com/apangin/class-file-extractor (not exactly JVM TI, but idea is the same).