summaryrefslogtreecommitdiff
path: root/runtime/openjdkjvmti/OpenjdkJvmTi.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/openjdkjvmti/OpenjdkJvmTi.cc')
-rw-r--r--runtime/openjdkjvmti/OpenjdkJvmTi.cc75
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,