The day before yesterday, I was aware of the question: What is the principle of Apply Changes provided by Android Studio 3.5? One responded to JVMTI, but the respondent did not give the code. He saw https://github.com/Android Advance With Geektime/JVMTI_Sample project in github, and then he had this blog for practice.
So try to test it on 9.0 official simulator
2. Applying jvmti Principle to Calculate objectCode address: https://github.com/zjw-swun/JVMTI_Demo
Thank you once again for https://github.com/Android Advance With Geektime/JVMTI_Sample dododola
First of all, we need to understand what functions JVMTI supports. We need to see what functions jvmti.h provides. In fact, in the era of java 1.6, we have already supported custom JVMTI agent, but android has not been implemented. This time, it is used in the android studio 3.5 "Apply Changes" feature, so that android p (9.0) begins to support. With this feature, the lower version does not have this feature.
There is no api for calculating object size in android, but those who are familiar with java should know that Instrument has getObjectSize. Although android has the same name, they have different functions. To implement getObjectSize, JVMTI is not available until this time when android p(9.0) supports it. Here the getObjectSize method can also be calculated by itself, and the calculation rules can be referred to. https://www.jb51.net/article/59809.htm Continue to look at jvmti.h, search for the keyword getObjectSize, and find the target code
jvmtiError GetObjectSize(jobject object, jlong* size_ptr) { return functions->GetObjectSize(this, object, size_ptr); }
On the basis of Dalao Source and Repository, native-lib.cpp adds the support of GetObjectSize function. You can refer to git submission record in detail. Here's 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; }
In JNI_OnLoad, a placeholder function {"getObjectSize", "(Ljava/lang/Object;) J", reinterpret_cast < jlong*> (tempGetObjectSize)} is dynamically registered, and the following statement is added before the JvmTI NativeMethodBind 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; }
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); }
Now that you have loaded jvmti.so, you can call getObjectSize
Of course, the JVMTIHelper.java category forgot to add JNI native functions
public static native long getObjectSize(Object obj);
Then the effect is the same as the one above.
3. jvmti. h has a lot of other functions to talk about.In short, the most anticipated RedfineClasses and Retransform Classes for jvmti.h are the keys to achieving Apply Changes