What is the principle of “Apply Changes” provided by Android Studio 3.5? Have an answer JVMTI, but a master did not give a code, see https://github.com/AndroidAdvanceWithGeektime/JVMTI_Sample in making the great spirit of the project, then this blog post practice
1. Let’s look at the effect first
1. First, Android P (9.0) started to support JVMTI
So try to test it on the 9.0 official simulator
2. Apply jVMTI principle to calculate object
Code address: github.com/zjw-swun/JV… Thanks again github.com/AndroidAdva… Dodola bosses
Jvmti agent: JVMti agent: jVMti agent: JVMti agent: JVMti agent: JVMti Agent This feature is available in Android Studio 3.5 with the “Apply Changes” feature, which will be available in Android P (9.0)
There is no API for calculating the size of an object, but if you are familiar with Java, you should know that the Instrument class has a getObjectSize method. To implement getObjectSize, this method is not provided until android P (9.0) supports JVMTI. The getObjectSize method can also be calculated by using www.jb51.net/article/598… H, search for the keyword getObjectSize and find the object code
jvmtiError GetObjectSize(jobject object,
jlong* size_ptr) {
return functions->GetObjectSize(this, object, size_ptr);
}
Copy the code
Native -lib. CPP added support for GetObjectSize function, details can refer to git submission record, the following is a brief introduction
extern "C" JNIEXPORT jlong JNICALL tempGetObjectSize(JNIEnv *env,
jclass clazz,
jobject obj) {
}
static JNINativeMethod methods[] = {
{"getObjectSize"."(Ljava/lang/Object;) J", reinterpret_cast<jlong *>(tempGetObjectSize)},
{"retransformClasses"."([Ljava/lang/Class;)V", reinterpret_cast<void *>(tempRetransformClasses)}
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
if(vm->GetEnv((void **) &env, JNI_VERSION_1_6) ! = JNI_OK) {return JNI_ERR;
}
ALOGI("==============library load====================");
jclass clazz = env->FindClass("com/dodola/jvmtilib/JVMTIHelper");
env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
return JNI_VERSION_1_6;
}
Copy the code
Dynamically register a {“getObjectSize”, “(Ljava/lang/Object;) in JNI_OnLoad. J”, reinterpret_cast
(tempGetObjectSize)}, then add the following statement to the JvmTINativeMethodBind function
extern "C" JNIEXPORT jlong JNICALL getObjectSize(JNIEnv *env, jclass clazz, jobject obj) {
jlong size;
jvmtiError result = localJvmtiEnv->GetObjectSize(obj, &size);
ALOGI("==========getObjectSize %d=======", size);
if(result ! = JVMTI_ERROR_NONE) { char *err;localJvmtiEnv->GetErrorName(result, &err);
printf("Failure running GetObjectSize: %s\n", err);
localJvmtiEnv->Deallocate(reinterpret_cast<unsigned char *>(err));
return- 1; }return size;
}
Copy the code
Add the following statement to the JvmTINativeMethodBind function
jmethodID methodid2 = jni_env->GetStaticMethodID(clazz, "getObjectSize"."(Ljava/lang/Object;) J");
if (methodid2 == method) {
*new_address_ptr = reinterpret_cast<jlong *>(&getObjectSize);
}
Copy the code
So now we’re done loading jvmti.so and then we can call getObjectSize
Of course the JVMtiHelper. Java class forgets to add JNI Native functions
public static native long getObjectSize(Object obj);
Copy the code
Then the effect will be the same as the above illustration
3. Jvmti. H has a lot of other functions
Jvmti. H RedefineClasses and RetransformClasses are the key to implementing Apply Changes