diff options
Diffstat (limited to 'runtime/openjdkjvmti/OpenjdkJvmTi.cc')
-rw-r--r-- | runtime/openjdkjvmti/OpenjdkJvmTi.cc | 75 |
1 files changed, 70 insertions, 5 deletions
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index d3561c1e1b..a1a23619f3 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -29,15 +29,17 @@ * questions. */ +#include <string> +#include <vector> + #include <jni.h> + #include "openjdkjvmti/jvmti.h" #include "art_jvmti.h" -#include "gc_root-inl.h" -#include "globals.h" #include "jni_env_ext-inl.h" -#include "scoped_thread_state_change.h" -#include "thread_list.h" +#include "runtime.h" +#include "transform.h" // TODO Remove this at some point by annotating all the methods. It was put in to make the skeleton // easier to create. @@ -904,6 +906,66 @@ class JvmtiFunctions { static jvmtiError GetJLocationFormat(jvmtiEnv* env, jvmtiJlocationFormat* format_ptr) { return ERR(NOT_IMPLEMENTED); } + + // TODO Remove this once events are working. + static jvmtiError RetransformClassWithHook(jvmtiEnv* env, + jclass klass, + jvmtiEventClassFileLoadHook hook) { + std::vector<jclass> classes; + classes.push_back(klass); + return RetransformClassesWithHook(reinterpret_cast<ArtJvmTiEnv*>(env), classes, hook); + } + + // TODO This will be called by the event handler for the art::ti Event Load Event + static jvmtiError RetransformClassesWithHook(ArtJvmTiEnv* env, + const std::vector<jclass>& classes, + jvmtiEventClassFileLoadHook hook) { + if (!IsValidEnv(env)) { + return ERR(INVALID_ENVIRONMENT); + } + for (jclass klass : classes) { + JNIEnv* jni_env = nullptr; + jobject loader = nullptr; + std::string name; + jobject protection_domain = nullptr; + jint data_len = 0; + unsigned char* dex_data = nullptr; + jvmtiError ret = OK; + std::string location; + if ((ret = GetTransformationData(env, + klass, + /*out*/&location, + /*out*/&jni_env, + /*out*/&loader, + /*out*/&name, + /*out*/&protection_domain, + /*out*/&data_len, + /*out*/&dex_data)) != OK) { + // TODO Do something more here? Maybe give log statements? + return ret; + } + jint new_data_len = 0; + unsigned char* new_dex_data = nullptr; + hook(env, + jni_env, + klass, + loader, + name.c_str(), + protection_domain, + data_len, + dex_data, + /*out*/&new_data_len, + /*out*/&new_dex_data); + // Check if anything actually changed. + if ((new_data_len != 0 || new_dex_data != nullptr) && new_dex_data != dex_data) { + MoveTransformedFileIntoRuntime(klass, std::move(location), new_data_len, new_dex_data); + env->Deallocate(new_dex_data); + } + // Deallocate the old dex data. + env->Deallocate(dex_data); + } + return OK; + } }; static bool IsJvmtiVersion(jint version) { @@ -942,7 +1004,10 @@ extern "C" bool ArtPlugin_Initialize() { // The actual struct holding all of the entrypoints into the jvmti interface. const jvmtiInterface_1 gJvmtiInterface = { - nullptr, // reserved1 + // SPECIAL FUNCTION: RetransformClassWithHook Is normally reserved1 + // TODO Remove once we have events working. + reinterpret_cast<void*>(JvmtiFunctions::RetransformClassWithHook), + // nullptr, // reserved1 JvmtiFunctions::SetEventNotificationMode, nullptr, // reserved3 JvmtiFunctions::GetAllThreads, |