diff options
author | 2017-03-30 10:26:59 -0700 | |
---|---|---|
committer | 2017-03-30 16:58:56 -0700 | |
commit | 3f46c96568bef650ba6d9ce6ac8835d30877f243 (patch) | |
tree | 86b0e0d10999dd4c7b525b1e4e2db3ab1703cbe0 | |
parent | 02311bd39d64b1417e8580c2a993620c2234254d (diff) |
ART: Refactor JVMTI run tests
In preparation for code deduplication with CTS.
Bug: 32072923
Test: m
Change-Id: Ibbe005c94252bd29eae7f88aad301b0b20ddb80d
40 files changed, 1111 insertions, 463 deletions
diff --git a/test/901-hello-ti-agent/basics.cc b/test/901-hello-ti-agent/basics.cc index cbd768663b..00776ca88c 100644 --- a/test/901-hello-ti-agent/basics.cc +++ b/test/901-hello-ti-agent/basics.cc @@ -24,8 +24,9 @@ #include "base/macros.h" #include "jvmti.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test901HelloTi { @@ -148,14 +149,14 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setVerboseFlag( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jint iflag, jboolean val) { jvmtiVerboseFlag flag = static_cast<jvmtiVerboseFlag>(iflag); jvmtiError result = jvmti_env->SetVerboseFlag(flag, val); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkLivePhase( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jvmtiPhase current_phase; jvmtiError phase_result = jvmti_env->GetPhase(¤t_phase); - if (JvmtiErrorToException(env, phase_result)) { + if (JvmtiErrorToException(env, jvmti_env, phase_result)) { return JNI_FALSE; } return (current_phase == JVMTI_PHASE_LIVE) ? JNI_TRUE : JNI_FALSE; diff --git a/test/903-hello-tagging/tagging.cc b/test/903-hello-tagging/tagging.cc index b85ed48930..7f079a259a 100644 --- a/test/903-hello-tagging/tagging.cc +++ b/test/903-hello-tagging/tagging.cc @@ -26,36 +26,25 @@ #include "art_method-inl.h" #include "base/logging.h" #include "jvmti.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" #include "utils.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" + namespace art { namespace Test903HelloTagging { -extern "C" JNIEXPORT void JNICALL Java_Main_setTag(JNIEnv* env ATTRIBUTE_UNUSED, - jclass, - jobject obj, - jlong tag) { +extern "C" JNIEXPORT void JNICALL Java_Main_setTag(JNIEnv* env, jclass, jobject obj, jlong tag) { jvmtiError ret = jvmti_env->SetTag(obj, tag); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Error setting tag: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); - } + JvmtiErrorToException(env, jvmti_env, ret); } -extern "C" JNIEXPORT jlong JNICALL Java_Main_getTag(JNIEnv* env ATTRIBUTE_UNUSED, - jclass, - jobject obj) { +extern "C" JNIEXPORT jlong JNICALL Java_Main_getTag(JNIEnv* env, jclass, jobject obj) { jlong tag = 0; jvmtiError ret = jvmti_env->GetTag(obj, &tag); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Error getting tag: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, ret)) { + return 0; } return tag; } @@ -86,11 +75,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getTaggedObjects(JNIEnv* env &result_count, result_object_array_ptr, result_tag_array_ptr); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Failure running GetLoadedClasses: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } @@ -197,4 +182,3 @@ extern "C" JNIEXPORT jlongArray JNICALL Java_Main_testTagsInDifferentEnvs( } // namespace Test903HelloTagging } // namespace art - diff --git a/test/904-object-allocation/tracking.cc b/test/904-object-allocation/tracking.cc index cc6f681d79..303f954b3b 100644 --- a/test/904-object-allocation/tracking.cc +++ b/test/904-object-allocation/tracking.cc @@ -24,10 +24,12 @@ #include "jvmti.h" #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" #include "utils.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" + namespace art { namespace Test904ObjectAllocation { @@ -57,21 +59,16 @@ static void JNICALL ObjectAllocated(jvmtiEnv* ti_env ATTRIBUTE_UNUSED, } extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectAllocCallback( - JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED, jboolean enable) { + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jboolean enable) { jvmtiEventCallbacks callbacks; memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); callbacks.VMObjectAlloc = enable ? ObjectAllocated : nullptr; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Error setting callbacks: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); - } + JvmtiErrorToException(env, jvmti_env, ret); } -extern "C" JNIEXPORT void JNICALL Java_Main_enableAllocationTracking(JNIEnv* env ATTRIBUTE_UNUSED, +extern "C" JNIEXPORT void JNICALL Java_Main_enableAllocationTracking(JNIEnv* env, jclass, jthread thread, jboolean enable) { @@ -79,14 +76,8 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableAllocationTracking(JNIEnv* env enable ? JVMTI_ENABLE : JVMTI_DISABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, thread); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Error enabling/disabling allocation tracking: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); - } + JvmtiErrorToException(env, jvmti_env, ret); } } // namespace Test904ObjectAllocation } // namespace art - diff --git a/test/905-object-free/tracking_free.cc b/test/905-object-free/tracking_free.cc index c48930987c..68ce38d9d9 100644 --- a/test/905-object-free/tracking_free.cc +++ b/test/905-object-free/tracking_free.cc @@ -24,10 +24,12 @@ #include "jvmti.h" #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" #include "utils.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" + namespace art { namespace Test905ObjectFree { @@ -46,52 +48,39 @@ static void JNICALL ObjectFree2(jvmtiEnv* ti_env, jlong tag) { collected_tags2.push_back(tag); } -static void setupObjectFreeCallback(jvmtiEnv* env, jvmtiEventObjectFree callback) { +static void setupObjectFreeCallback(JNIEnv* env, jvmtiEnv* jenv, jvmtiEventObjectFree callback) { jvmtiEventCallbacks callbacks; memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); callbacks.ObjectFree = callback; - jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - if (ret != JVMTI_ERROR_NONE) { - char* err; - env->GetErrorName(ret, &err); - printf("Error setting callbacks: %s\n", err); - env->Deallocate(reinterpret_cast<unsigned char*>(err)); - } + jvmtiError ret = jenv->SetEventCallbacks(&callbacks, sizeof(callbacks)); + JvmtiErrorToException(env, jenv, ret); } extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectFreeCallback( JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) { - setupObjectFreeCallback(jvmti_env, ObjectFree1); + setupObjectFreeCallback(env, jvmti_env, ObjectFree1); JavaVM* jvm = nullptr; env->GetJavaVM(&jvm); CHECK_EQ(jvm->GetEnv(reinterpret_cast<void**>(&jvmti_env2), JVMTI_VERSION_1_2), 0); SetAllCapabilities(jvmti_env2); - setupObjectFreeCallback(jvmti_env2, ObjectFree2); + setupObjectFreeCallback(env, jvmti_env2, ObjectFree2); } -extern "C" JNIEXPORT void JNICALL Java_Main_enableFreeTracking(JNIEnv* env ATTRIBUTE_UNUSED, +extern "C" JNIEXPORT void JNICALL Java_Main_enableFreeTracking(JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jboolean enable) { jvmtiError ret = jvmti_env->SetEventNotificationMode( enable ? JVMTI_ENABLE : JVMTI_DISABLE, JVMTI_EVENT_OBJECT_FREE, nullptr); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Error enabling/disabling object-free callbacks: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, ret)) { + return; } ret = jvmti_env2->SetEventNotificationMode( enable ? JVMTI_ENABLE : JVMTI_DISABLE, JVMTI_EVENT_OBJECT_FREE, nullptr); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env2->GetErrorName(ret, &err); - printf("Error enabling/disabling object-free callbacks: %s\n", err); - jvmti_env2->Deallocate(reinterpret_cast<unsigned char*>(err)); - } + JvmtiErrorToException(env, jvmti_env, ret); } extern "C" JNIEXPORT jlongArray JNICALL Java_Main_getCollectedTags(JNIEnv* env, @@ -114,7 +103,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setTag2(JNIEnv* env, jobject obj, jlong tag) { jvmtiError ret = jvmti_env2->SetTag(obj, tag); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); } } // namespace Test905ObjectFree diff --git a/test/906-iterate-heap/iterate_heap.cc b/test/906-iterate-heap/iterate_heap.cc index f2532debfb..74cb1e9c1f 100644 --- a/test/906-iterate-heap/iterate_heap.cc +++ b/test/906-iterate-heap/iterate_heap.cc @@ -28,10 +28,12 @@ #include "jni.h" #include "jvmti.h" #include "ScopedPrimitiveArray.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" #include "utf.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" + namespace art { namespace Test906IterateHeap { @@ -52,7 +54,7 @@ static jint JNICALL HeapIterationCallback(jlong class_tag, return config->Handle(class_tag, size, tag_ptr, length); } -static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config) { +static bool Run(JNIEnv* env, jint heap_filter, jclass klass_filter, IterationConfig* config) { jvmtiHeapCallbacks callbacks; memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks)); callbacks.heap_iteration_callback = HeapIterationCallback; @@ -61,17 +63,13 @@ static bool Run(jint heap_filter, jclass klass_filter, IterationConfig* config) klass_filter, &callbacks, config); - if (ret != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(ret, &err); - printf("Failure running IterateThroughHeap: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, ret)) { return false; } return true; } -extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapCount(JNIEnv* env ATTRIBUTE_UNUSED, +extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapCount(JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jint heap_filter, jclass klass_filter, @@ -99,7 +97,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapCount(JNIEnv* env }; CountIterationConfig config(0, stop_after); - Run(heap_filter, klass_filter, &config); + Run(env, heap_filter, klass_filter, &config); if (config.counter > config.stop_after) { printf("Error: more objects visited than signaled."); @@ -135,7 +133,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapData(JNIEnv* env, }; DataIterationConfig config; - if (!Run(heap_filter, klass_filter, &config)) { + if (!Run(env, heap_filter, klass_filter, &config)) { return -1; } @@ -154,7 +152,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_iterateThroughHeapData(JNIEnv* env, return static_cast<jint>(config.class_tags_.size()); } -extern "C" JNIEXPORT void JNICALL Java_Main_iterateThroughHeapAdd(JNIEnv* env ATTRIBUTE_UNUSED, +extern "C" JNIEXPORT void JNICALL Java_Main_iterateThroughHeapAdd(JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jint heap_filter, jclass klass_filter) { @@ -175,7 +173,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_iterateThroughHeapAdd(JNIEnv* env AT }; AddIterationConfig config; - Run(heap_filter, klass_filter, &config); + Run(env, heap_filter, klass_filter, &config); } extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapString( @@ -228,7 +226,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapString( FindStringCallbacks fsc(tag); jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &fsc); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } return env->NewStringUTF(fsc.data.c_str()); @@ -316,7 +314,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapPrimitiveArray( FindArrayCallbacks fac(tag); jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &fac); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } return env->NewStringUTF(fac.data.c_str()); @@ -403,7 +401,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_iterateThroughHeapPrimitiveFields FindFieldCallbacks ffc(tag); jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &ffc); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } return env->NewStringUTF(ffc.data.c_str()); diff --git a/test/907-get-loaded-classes/get_loaded_classes.cc b/test/907-get-loaded-classes/get_loaded_classes.cc index 48ce2e2de1..1b973bf2be 100644 --- a/test/907-get-loaded-classes/get_loaded_classes.cc +++ b/test/907-get-loaded-classes/get_loaded_classes.cc @@ -25,8 +25,9 @@ #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "test_env.h" namespace art { namespace Test907GetLoadedClasses { diff --git a/test/908-gc-start-finish/gc_callbacks.cc b/test/908-gc-start-finish/gc_callbacks.cc index 45148f87cd..4b9a23cede 100644 --- a/test/908-gc-start-finish/gc_callbacks.cc +++ b/test/908-gc-start-finish/gc_callbacks.cc @@ -20,8 +20,10 @@ #include "base/macros.h" #include "jni.h" #include "jvmti.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" + +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test908GcStartFinish { @@ -45,7 +47,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setupGcCallback( callbacks.GarbageCollectionStart = GarbageCollectionStart; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); } extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env, @@ -55,14 +57,14 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableGcTracking(JNIEnv* env, enable ? JVMTI_ENABLE : JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode( enable ? JVMTI_ENABLE : JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } } diff --git a/test/910-methods/methods.cc b/test/910-methods/methods.cc index fdc4cdbe04..429076c386 100644 --- a/test/910-methods/methods.cc +++ b/test/910-methods/methods.cc @@ -21,8 +21,10 @@ #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test910Methods { @@ -35,11 +37,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName( char* sig; char* gen; jvmtiError result = jvmti_env->GetMethodName(id, &name, &sig, &gen); - if (result != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(result, &err); - printf("Failure running GetMethodName: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -67,11 +65,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getMethodName( // Also run GetMethodName with all parameter pointers null to check for segfaults. jvmtiError result2 = jvmti_env->GetMethodName(id, nullptr, nullptr, nullptr); - if (result2 != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(result2, &err); - printf("Failure running GetMethodName(null, null, null): %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, result2)) { return nullptr; } @@ -84,11 +78,7 @@ extern "C" JNIEXPORT jclass JNICALL Java_Main_getMethodDeclaringClass( jclass declaring_class; jvmtiError result = jvmti_env->GetMethodDeclaringClass(id, &declaring_class); - if (result != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(result, &err); - printf("Failure running GetMethodDeclaringClass: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -101,11 +91,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getMethodModifiers( jint modifiers; jvmtiError result = jvmti_env->GetMethodModifiers(id, &modifiers); - if (result != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(result, &err); - printf("Failure running GetMethodModifiers: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + if (JvmtiErrorToException(env, jvmti_env, result)) { return 0; } @@ -118,7 +104,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getMaxLocals( jint max_locals; jvmtiError result = jvmti_env->GetMaxLocals(id, &max_locals); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } @@ -131,7 +117,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getArgumentsSize( jint arguments; jvmtiError result = jvmti_env->GetArgumentsSize(id, &arguments); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } @@ -145,7 +131,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getMethodLocationStart( jlong start; jlong end; jvmtiError result = jvmti_env->GetMethodLocation(id, &start, &end); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } @@ -159,7 +145,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getMethodLocationEnd( jlong start; jlong end; jvmtiError result = jvmti_env->GetMethodLocation(id, &start, &end); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } @@ -172,7 +158,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodNative( jboolean is_native; jvmtiError result = jvmti_env->IsMethodNative(id, &is_native); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return JNI_FALSE; } @@ -185,7 +171,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodObsolete( jboolean is_obsolete; jvmtiError result = jvmti_env->IsMethodObsolete(id, &is_obsolete); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return JNI_FALSE; } @@ -198,7 +184,7 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_isMethodSynthetic( jboolean is_synthetic; jvmtiError result = jvmti_env->IsMethodSynthetic(id, &is_synthetic); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return JNI_FALSE; } diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc index 5a3a311255..49cbb7e3c5 100644 --- a/test/911-get-stack-trace/stack_trace.cc +++ b/test/911-get-stack-trace/stack_trace.cc @@ -26,8 +26,12 @@ #include "jni.h" #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" + +// Test infrastructure +#include "jni_binder.h" +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test911GetStackTrace { @@ -68,7 +72,7 @@ static jobjectArray TranslateJvmtiFrameInfoArray(JNIEnv* env, char* gen; { jvmtiError result2 = jvmti_env->GetMethodName(frames[method_index].method, &name, &sig, &gen); - if (JvmtiErrorToException(env, result2)) { + if (JvmtiErrorToException(env, jvmti_env, result2)) { return nullptr; } } @@ -83,10 +87,7 @@ static jobjectArray TranslateJvmtiFrameInfoArray(JNIEnv* env, // Accept absent info and native method errors. if (line_result != JVMTI_ERROR_ABSENT_INFORMATION && line_result != JVMTI_ERROR_NATIVE_METHOD) { - char* err; - jvmti_env->GetErrorName(line_result, &err); - printf("Failure running GetLineNumberTable: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + JvmtiErrorToException(env, jvmti_env, line_result); return nullptr; } line_number_table = nullptr; @@ -139,7 +140,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_PrintThread_getStackTrace( jint count; { jvmtiError result = jvmti_env->GetStackTrace(thread, start, max, frames.get(), &count); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } } @@ -153,7 +154,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_AllTraces_getAllStackTraces( jvmtiStackInfo* stack_infos; { jvmtiError result = jvmti_env->GetAllStackTraces(max, &stack_infos, &thread_count); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } } @@ -189,7 +190,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_ThreadListTraces_getThreadListSta threads.get(), max, &stack_infos); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } } @@ -215,7 +216,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Frames_getFrameCount( JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thread) { jint count; jvmtiError result = jvmti_env->GetFrameCount(thread, &count); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } return count; @@ -227,7 +228,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Frames_getFrameLocation( jlocation location; jvmtiError result = jvmti_env->GetFrameLocation(thread, depth, &method, &location); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -237,12 +238,12 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Frames_getFrameLocation( { jclass decl_class; jvmtiError class_result = jvmti_env->GetMethodDeclaringClass(method, &decl_class); - if (JvmtiErrorToException(env, class_result)) { + if (JvmtiErrorToException(env, jvmti_env, class_result)) { return nullptr; } jint modifiers; jvmtiError mod_result = jvmti_env->GetMethodModifiers(method, &modifiers); - if (JvmtiErrorToException(env, mod_result)) { + if (JvmtiErrorToException(env, jvmti_env, mod_result)) { return nullptr; } constexpr jint kStatic = 0x8; diff --git a/test/912-classes/classes.cc b/test/912-classes/classes.cc index 5bd34f6be8..4d84e393d1 100644 --- a/test/912-classes/classes.cc +++ b/test/912-classes/classes.cc @@ -27,8 +27,10 @@ #include "scoped_thread_state_change-inl.h" #include "thread-inl.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test912Classes { @@ -233,7 +235,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getClassLoaderClasses( jint count = 0; jclass* classes = nullptr; jvmtiError result = jvmti_env->GetClassLoaderClasses(jclassloader, &count, &classes); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -251,7 +253,7 @@ extern "C" JNIEXPORT jintArray JNICALL Java_Main_getClassVersion( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jclass klass) { jint major, minor; jvmtiError result = jvmti_env->GetClassVersionNumbers(klass, &minor, &major); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -270,7 +272,7 @@ static std::string GetClassName(jvmtiEnv* jenv, JNIEnv* jni_env, jclass klass) { jvmtiError result = jenv->GetClassSignature(klass, &name, nullptr); if (result != JVMTI_ERROR_NONE) { if (jni_env != nullptr) { - JvmtiErrorToException(jni_env, result); + JvmtiErrorToException(jni_env, jenv, result); } else { printf("Failed to get class signature.\n"); } @@ -291,13 +293,13 @@ static void EnableEvents(JNIEnv* env, jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_CLASS_LOAD, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_CLASS_PREPARE, nullptr); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); return; } @@ -306,20 +308,20 @@ static void EnableEvents(JNIEnv* env, callbacks.ClassLoad = class_load; callbacks.ClassPrepare = class_prepare; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, nullptr); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); } class ClassLoadPreparePrinter { @@ -364,7 +366,7 @@ class ClassLoadPreparePrinter { jvmtiError result = jenv->GetThreadInfo(thread, &info); if (result != JVMTI_ERROR_NONE) { if (jni_env != nullptr) { - JvmtiErrorToException(jni_env, result); + JvmtiErrorToException(jni_env, jenv, result); } else { printf("Failed to get thread name.\n"); } diff --git a/test/913-heaps/heaps.cc b/test/913-heaps/heaps.cc index 66fc7bef9a..999467f443 100644 --- a/test/913-heaps/heaps.cc +++ b/test/913-heaps/heaps.cc @@ -34,8 +34,10 @@ #include "thread-inl.h" #include "thread_list.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test913Heaps { @@ -550,7 +552,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_followReferencesString( FindStringCallbacks fsc; jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &fsc); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } @@ -648,7 +650,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_followReferencesPrimitiveArray( FindArrayCallbacks fac; jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &fac); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } return env->NewStringUTF(fac.data.c_str()); @@ -738,7 +740,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_followReferencesPrimitiveFields( FindFieldCallbacks ffc; jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &ffc); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return nullptr; } return env->NewStringUTF(ffc.data.c_str()); diff --git a/test/918-fields/fields.cc b/test/918-fields/fields.cc index c659126aae..0c019e3dbb 100644 --- a/test/918-fields/fields.cc +++ b/test/918-fields/fields.cc @@ -21,8 +21,9 @@ #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "test_env.h" namespace art { namespace Test918Fields { diff --git a/test/920-objects/objects.cc b/test/920-objects/objects.cc index ad1431ed00..1dfb516c79 100644 --- a/test/920-objects/objects.cc +++ b/test/920-objects/objects.cc @@ -21,8 +21,8 @@ #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "test_env.h" namespace art { namespace Test920Objects { diff --git a/test/922-properties/properties.cc b/test/922-properties/properties.cc index 3fd274e9d6..948da6a5bb 100644 --- a/test/922-properties/properties.cc +++ b/test/922-properties/properties.cc @@ -21,8 +21,10 @@ #include "jvmti.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test922Properties { @@ -32,7 +34,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getSystemProperties( jint count; char** properties; jvmtiError result = jvmti_env->GetSystemProperties(&count, &properties); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -61,7 +63,7 @@ extern "C" JNIEXPORT jstring JNICALL Java_Main_getSystemProperty( char* value = nullptr; jvmtiError result = jvmti_env->GetSystemProperty(string.c_str(), &value); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -84,7 +86,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setSystemProperty( } jvmtiError result = jvmti_env->SetSystemProperty(key_string.c_str(), value_string.c_str()); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return; } } diff --git a/test/923-monitors/monitors.cc b/test/923-monitors/monitors.cc index 131fc6a4d4..60d5b5a941 100644 --- a/test/923-monitors/monitors.cc +++ b/test/923-monitors/monitors.cc @@ -21,8 +21,9 @@ #include "jvmti.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test923Monitors { @@ -40,7 +41,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_createRawMonitor( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jrawMonitorID id; jvmtiError result = jvmti_env->CreateRawMonitor("dummy", &id); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return 0; } return MonitorToLong(id); @@ -49,37 +50,37 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_createRawMonitor( extern "C" JNIEXPORT void JNICALL Java_Main_destroyRawMonitor( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l) { jvmtiError result = jvmti_env->DestroyRawMonitor(LongToMonitor(l)); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_rawMonitorEnter( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l) { jvmtiError result = jvmti_env->RawMonitorEnter(LongToMonitor(l)); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_rawMonitorExit( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l) { jvmtiError result = jvmti_env->RawMonitorExit(LongToMonitor(l)); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_rawMonitorWait( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l, jlong millis) { jvmtiError result = jvmti_env->RawMonitorWait(LongToMonitor(l), millis); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_rawMonitorNotify( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l) { jvmtiError result = jvmti_env->RawMonitorNotify(LongToMonitor(l)); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_rawMonitorNotifyAll( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jlong l) { jvmtiError result = jvmti_env->RawMonitorNotifyAll(LongToMonitor(l)); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } } // namespace Test923Monitors diff --git a/test/924-threads/threads.cc b/test/924-threads/threads.cc index 14ea5af60e..bb040bdb2b 100644 --- a/test/924-threads/threads.cc +++ b/test/924-threads/threads.cc @@ -23,8 +23,10 @@ #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test924Threads { @@ -36,7 +38,7 @@ extern "C" JNIEXPORT jthread JNICALL Java_Main_getCurrentThread( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jthread thread = nullptr; jvmtiError result = jvmti_env->GetCurrentThread(&thread); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } return thread; @@ -48,7 +50,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getThreadInfo( memset(&info, 0, sizeof(jvmtiThreadInfo)); jvmtiError result = jvmti_env->GetThreadInfo(thread, &info); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -94,7 +96,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getThreadState( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jthread thread) { jint state; jvmtiError result = jvmti_env->GetThreadState(thread, &state); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return 0; } return state; @@ -106,7 +108,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getAllThreads( jthread* threads; jvmtiError result = jvmti_env->GetAllThreads(&thread_count, &threads); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -124,7 +126,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getTLS( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jthread thread) { void* tls; jvmtiError result = jvmti_env->GetThreadLocalStorage(thread, &tls); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return 0; } return static_cast<jlong>(reinterpret_cast<uintptr_t>(tls)); @@ -134,7 +136,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_setTLS( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jthread thread, jlong val) { const void* tls = reinterpret_cast<void*>(static_cast<uintptr_t>(val)); jvmtiError result = jvmti_env->SetThreadLocalStorage(thread, tls); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } static void JNICALL ThreadEvent(jvmtiEnv* jvmti_env, @@ -172,13 +174,13 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableThreadEvents( jvmtiError ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_THREAD_START, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_THREAD_END, nullptr); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); return; } @@ -187,20 +189,20 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableThreadEvents( callbacks.ThreadStart = ThreadStart; callbacks.ThreadEnd = ThreadEnd; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, nullptr); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); } } // namespace Test924Threads diff --git a/test/925-threadgroups/threadgroups.cc b/test/925-threadgroups/threadgroups.cc index 2feaab079b..1cd93bea3b 100644 --- a/test/925-threadgroups/threadgroups.cc +++ b/test/925-threadgroups/threadgroups.cc @@ -23,8 +23,10 @@ #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test925ThreadGroups { @@ -38,7 +40,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getTopThreadGroups( jthreadGroup* groups; jint group_count; jvmtiError result = jvmti_env->GetTopThreadGroups(&group_count, &groups); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -56,7 +58,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getThreadGroupInfo( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED, jthreadGroup group) { jvmtiThreadGroupInfo info; jvmtiError result = jvmti_env->GetThreadGroupInfo(group, &info); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } @@ -96,7 +98,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getThreadGroupChildren( &threads, &threadgroup_count, &groups); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } diff --git a/test/927-timers/timers.cc b/test/927-timers/timers.cc index 7b1d5c3f52..a67f5b47e0 100644 --- a/test/927-timers/timers.cc +++ b/test/927-timers/timers.cc @@ -22,8 +22,10 @@ #include "jni.h" #include "jvmti.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_helper.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test926Timers { @@ -32,7 +34,7 @@ extern "C" JNIEXPORT jint JNICALL Java_Main_getAvailableProcessors( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jint count; jvmtiError result = jvmti_env->GetAvailableProcessors(&count); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } return count; @@ -42,7 +44,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_Main_getTime( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jlong time; jvmtiError result = jvmti_env->GetTime(&time); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return -1; } return time; @@ -52,7 +54,7 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getTimerInfo( JNIEnv* env, jclass Main_klass ATTRIBUTE_UNUSED) { jvmtiTimerInfo info; jvmtiError result = jvmti_env->GetTimerInfo(&info); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return nullptr; } diff --git a/test/928-jni-table/jni_table.cc b/test/928-jni-table/jni_table.cc index b5c0efdd95..3f4a93e147 100644 --- a/test/928-jni-table/jni_table.cc +++ b/test/928-jni-table/jni_table.cc @@ -22,8 +22,9 @@ #include "base/logging.h" #include "base/macros.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test927JNITable { @@ -42,14 +43,14 @@ extern "C" JNIEXPORT void JNICALL Java_Main_doJNITableTest( JNIEnv* env, jclass klass) { // Get the current table, as the delegate. jvmtiError getorig_result = jvmti_env->GetJNIFunctionTable(&gOriginalEnv); - if (JvmtiErrorToException(env, getorig_result)) { + if (JvmtiErrorToException(env, jvmti_env, getorig_result)) { return; } // Get the current table, as the override we'll install. JNINativeInterface* env_override; jvmtiError getoverride_result = jvmti_env->GetJNIFunctionTable(&env_override); - if (JvmtiErrorToException(env, getoverride_result)) { + if (JvmtiErrorToException(env, jvmti_env, getoverride_result)) { return; } @@ -58,7 +59,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_doJNITableTest( // Install the override. jvmtiError setoverride_result = jvmti_env->SetJNIFunctionTable(env_override); - if (JvmtiErrorToException(env, setoverride_result)) { + if (JvmtiErrorToException(env, jvmti_env, setoverride_result)) { return; } @@ -68,7 +69,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_doJNITableTest( // Install the "original." There is no real reset. jvmtiError setoverride2_result = jvmti_env->SetJNIFunctionTable(gOriginalEnv); - if (JvmtiErrorToException(env, setoverride2_result)) { + if (JvmtiErrorToException(env, jvmti_env, setoverride2_result)) { return; } diff --git a/test/929-search/search.cc b/test/929-search/search.cc index ad7a05323b..bed4dfeb65 100644 --- a/test/929-search/search.cc +++ b/test/929-search/search.cc @@ -23,8 +23,9 @@ #include "jvmti.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test929Search { @@ -36,7 +37,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_addToBootClassLoader( return; } jvmtiError result = jvmti_env->AddToBootstrapClassLoaderSearch(utf.c_str()); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } extern "C" JNIEXPORT void JNICALL Java_Main_addToSystemClassLoader( @@ -46,7 +47,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_addToSystemClassLoader( return; } jvmtiError result = jvmti_env->AddToSystemClassLoaderSearch(utf.c_str()); - JvmtiErrorToException(env, result); + JvmtiErrorToException(env, jvmti_env, result); } } // namespace Test929Search diff --git a/test/931-agent-thread/agent_thread.cc b/test/931-agent-thread/agent_thread.cc index 2e6bd46f4e..3ec8793f89 100644 --- a/test/931-agent-thread/agent_thread.cc +++ b/test/931-agent-thread/agent_thread.cc @@ -27,8 +27,9 @@ #include "thread-inl.h" #include "well_known_classes.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test930AgentThread { @@ -53,13 +54,13 @@ static void AgentMain(jvmtiEnv* jenv, JNIEnv* env, void* arg) { // This thread is not the main thread. jthread this_thread; jvmtiError this_thread_result = jenv->GetCurrentThread(&this_thread); - CHECK(!JvmtiErrorToException(env, this_thread_result)); + CHECK(!JvmtiErrorToException(env, jenv, this_thread_result)); CHECK(!env->IsSameObject(this_thread, data->main_thread)); // The thread is a daemon. jvmtiThreadInfo info; jvmtiError info_result = jenv->GetThreadInfo(this_thread, &info); - CHECK(!JvmtiErrorToException(env, info_result)); + CHECK(!JvmtiErrorToException(env, jenv, info_result)); CHECK(info.is_daemon); // The thread has the requested priority. @@ -70,7 +71,7 @@ static void AgentMain(jvmtiEnv* jenv, JNIEnv* env, void* arg) { jint thread_count; jthread* threads; jvmtiError threads_result = jenv->GetAllThreads(&thread_count, &threads); - CHECK(!JvmtiErrorToException(env, threads_result)); + CHECK(!JvmtiErrorToException(env, jenv, threads_result)); bool found = false; for (jint i = 0; i != thread_count; ++i) { if (env->IsSameObject(threads[i], this_thread)) { @@ -111,7 +112,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testAgentThread( jthread main_thread; jvmtiError main_thread_result = jvmti_env->GetCurrentThread(&main_thread); - if (JvmtiErrorToException(env, main_thread_result)) { + if (JvmtiErrorToException(env, jvmti_env, main_thread_result)) { return; } @@ -121,7 +122,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testAgentThread( data.priority = JVMTI_THREAD_MIN_PRIORITY; jvmtiError result = jvmti_env->RunAgentThread(thread.get(), AgentMain, &data, data.priority); - if (JvmtiErrorToException(env, result)) { + if (JvmtiErrorToException(env, jvmti_env, result)) { return; } @@ -133,7 +134,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testAgentThread( NanoSleep(1000 * 1000); jint thread_state; jvmtiError state_result = jvmti_env->GetThreadState(thread.get(), &thread_state); - if (JvmtiErrorToException(env, state_result)) { + if (JvmtiErrorToException(env, jvmti_env, state_result)) { return; } if (thread_state == 0 || // Was never alive. diff --git a/test/933-misc-events/misc_events.cc b/test/933-misc-events/misc_events.cc index 7043350b5a..7b6c64d1fb 100644 --- a/test/933-misc-events/misc_events.cc +++ b/test/933-misc-events/misc_events.cc @@ -23,8 +23,9 @@ #include "jni.h" #include "jvmti.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test933MiscEvents { @@ -42,14 +43,14 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testSigQuit( memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); callbacks.DataDumpRequest = DumpRequestCallback; jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } ret = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, nullptr); - if (JvmtiErrorToException(env, ret)) { + if (JvmtiErrorToException(env, jvmti_env, ret)) { return; } @@ -65,7 +66,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_testSigQuit( } ret = jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, nullptr); - JvmtiErrorToException(env, ret); + JvmtiErrorToException(env, jvmti_env, ret); } } // namespace Test933MiscEvents diff --git a/test/936-search-onload/search_onload.cc b/test/936-search-onload/search_onload.cc index 3b19ca591d..72987eb358 100644 --- a/test/936-search-onload/search_onload.cc +++ b/test/936-search-onload/search_onload.cc @@ -25,8 +25,9 @@ #include "jvmti.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test936SearchOnload { diff --git a/test/944-transform-classloaders/classloader.cc b/test/944-transform-classloaders/classloader.cc index 7cb3c08dc3..f46763c2f1 100644 --- a/test/944-transform-classloaders/classloader.cc +++ b/test/944-transform-classloaders/classloader.cc @@ -20,8 +20,8 @@ #include "mirror/class-inl.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "test_env.h" namespace art { namespace Test944TransformClassloaders { diff --git a/test/945-obsolete-native/obsolete_native.cc b/test/945-obsolete-native/obsolete_native.cc index 442836b7ff..b9303dda27 100644 --- a/test/945-obsolete-native/obsolete_native.cc +++ b/test/945-obsolete-native/obsolete_native.cc @@ -26,8 +26,10 @@ #include "jni.h" #include "jvmti.h" #include "ScopedLocalRef.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" + +// Test infrastructure +#include "jni_binder.h" +#include "test_env.h" namespace art { namespace Test945ObsoleteNative { diff --git a/test/980-redefine-object/redefine_object.cc b/test/980-redefine-object/redefine_object.cc index daae08792a..6c8c4bd2f0 100644 --- a/test/980-redefine-object/redefine_object.cc +++ b/test/980-redefine-object/redefine_object.cc @@ -24,8 +24,10 @@ #include "jvmti.h" #include "ScopedUtfChars.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jni_binder.h" +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test980RedefineObjects { @@ -39,9 +41,11 @@ extern "C" JNIEXPORT void JNICALL Java_art_test_TestWatcher_NotifyConstructed( JNIEnv* env, jclass TestWatcherClass ATTRIBUTE_UNUSED, jobject constructed) { char* sig = nullptr; char* generic_sig = nullptr; - if (JvmtiErrorToException(env, jvmti_env->GetClassSignature(env->GetObjectClass(constructed), - &sig, - &generic_sig))) { + if (JvmtiErrorToException(env, + jvmti_env, + jvmti_env->GetClassSignature(env->GetObjectClass(constructed), + &sig, + &generic_sig))) { // Exception. return; } diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc index e8b7e13dcf..3ef3c7cb45 100644 --- a/test/983-source-transform-verify/source_transform.cc +++ b/test/983-source-transform-verify/source_transform.cc @@ -37,8 +37,9 @@ #include "thread-inl.h" #include "thread_list.h" -#include "ti-agent/common_helper.h" -#include "ti-agent/common_load.h" +// Test infrastructure +#include "jvmti_helper.h" +#include "test_env.h" namespace art { namespace Test983SourceTransformVerify { diff --git a/test/Android.bp b/test/Android.bp index ec40acf279..2e8f5bb6f8 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -249,6 +249,9 @@ art_cc_defaults { "common/runtime_state.cc", "ti-agent/common_load.cc", "ti-agent/common_helper.cc", + "ti-agent/jni_binder.cc", + "ti-agent/jvmti_helper.cc", + "ti-agent/test_env.cc", "901-hello-ti-agent/basics.cc", "903-hello-tagging/tagging.cc", "904-object-allocation/tracking.cc", @@ -282,6 +285,7 @@ art_cc_defaults { "libbase", ], header_libs: ["libopenjdkjvmti_headers"], + include_dirs: ["art/test/ti-agent"], } art_cc_test_library { diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc index 6316a9c368..ab5dbcc0db 100644 --- a/test/ti-agent/common_helper.cc +++ b/test/ti-agent/common_helper.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "ti-agent/common_helper.h" +#include "common_helper.h" #include <dlfcn.h> #include <stdio.h> @@ -27,44 +27,15 @@ #include "jni_internal.h" #include "jvmti.h" #include "scoped_thread_state_change-inl.h" -#include "ScopedLocalRef.h" #include "stack.h" -#include "ti-agent/common_load.h" #include "utils.h" -namespace art { -bool RuntimeIsJVM; - -bool IsJVM() { - return RuntimeIsJVM; -} - -void SetAllCapabilities(jvmtiEnv* env) { - jvmtiCapabilities caps; - env->GetPotentialCapabilities(&caps); - env->AddCapabilities(&caps); -} - -bool JvmtiErrorToException(JNIEnv* env, jvmtiError error) { - if (error == JVMTI_ERROR_NONE) { - return false; - } - - ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); - if (rt_exception.get() == nullptr) { - // CNFE should be pending. - return true; - } - - char* err; - jvmti_env->GetErrorName(error, &err); - - env->ThrowNew(rt_exception.get(), err); - - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); - return true; -} +#include "jni_binder.h" +#include "jvmti_helper.h" +#include "scoped_local_ref.h" +#include "test_env.h" +namespace art { template <bool is_redefine> static void throwCommonRedefinitionError(jvmtiEnv* jvmti, @@ -303,7 +274,7 @@ extern "C" JNIEXPORT void Java_Main_enableCommonRetransformation(JNIEnv* env, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, nullptr); if (res != JVMTI_ERROR_NONE) { - JvmtiErrorToException(env, res); + JvmtiErrorToException(env, jvmti_env, res); } } @@ -412,140 +383,4 @@ jint OnLoad(JavaVM* vm, } // namespace common_transform -static void BindMethod(jvmtiEnv* jenv, - JNIEnv* env, - jclass klass, - jmethodID method) { - char* name; - char* signature; - jvmtiError name_result = jenv->GetMethodName(method, &name, &signature, nullptr); - if (name_result != JVMTI_ERROR_NONE) { - LOG(FATAL) << "Could not get methods"; - } - - std::string names[2]; - if (IsJVM()) { - // TODO Get the JNI long name - char* klass_name; - jvmtiError klass_result = jenv->GetClassSignature(klass, &klass_name, nullptr); - if (klass_result == JVMTI_ERROR_NONE) { - std::string name_str(name); - std::string klass_str(klass_name); - names[0] = GetJniShortName(klass_str, name_str); - jenv->Deallocate(reinterpret_cast<unsigned char*>(klass_name)); - } else { - LOG(FATAL) << "Could not get class name!"; - } - } else { - ScopedObjectAccess soa(Thread::Current()); - ArtMethod* m = jni::DecodeArtMethod(method); - names[0] = m->JniShortName(); - names[1] = m->JniLongName(); - } - for (const std::string& mangled_name : names) { - if (mangled_name == "") { - continue; - } - void* sym = dlsym(RTLD_DEFAULT, mangled_name.c_str()); - if (sym == nullptr) { - continue; - } - - JNINativeMethod native_method; - native_method.fnPtr = sym; - native_method.name = name; - native_method.signature = signature; - - env->RegisterNatives(klass, &native_method, 1); - - jenv->Deallocate(reinterpret_cast<unsigned char*>(name)); - jenv->Deallocate(reinterpret_cast<unsigned char*>(signature)); - return; - } - - LOG(FATAL) << "Could not find " << names[0]; -} - -static jclass FindClassWithSystemClassLoader(JNIEnv* env, const char* class_name) { - // Find the system classloader. - ScopedLocalRef<jclass> cl_klass(env, env->FindClass("java/lang/ClassLoader")); - if (cl_klass.get() == nullptr) { - return nullptr; - } - jmethodID getsystemclassloader_method = env->GetStaticMethodID(cl_klass.get(), - "getSystemClassLoader", - "()Ljava/lang/ClassLoader;"); - if (getsystemclassloader_method == nullptr) { - return nullptr; - } - ScopedLocalRef<jobject> cl(env, env->CallStaticObjectMethod(cl_klass.get(), - getsystemclassloader_method)); - if (cl.get() == nullptr) { - return nullptr; - } - - // Create a String of the name. - std::string descriptor = android::base::StringPrintf("L%s;", class_name); - std::string dot_name = DescriptorToDot(descriptor.c_str()); - ScopedLocalRef<jstring> name_str(env, env->NewStringUTF(dot_name.c_str())); - - // Call Class.forName with it. - ScopedLocalRef<jclass> c_klass(env, env->FindClass("java/lang/Class")); - if (c_klass.get() == nullptr) { - return nullptr; - } - jmethodID forname_method = env->GetStaticMethodID( - c_klass.get(), - "forName", - "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); - if (forname_method == nullptr) { - return nullptr; - } - - return reinterpret_cast<jclass>(env->CallStaticObjectMethod(c_klass.get(), - forname_method, - name_str.get(), - JNI_FALSE, - cl.get())); -} - -void BindFunctions(jvmtiEnv* jenv, JNIEnv* env, const char* class_name) { - // Use JNI to load the class. - ScopedLocalRef<jclass> klass(env, env->FindClass(class_name)); - if (klass.get() == nullptr) { - // We may be called with the wrong classloader. Try explicitly using the system classloader. - env->ExceptionClear(); - klass.reset(FindClassWithSystemClassLoader(env, class_name)); - if (klass.get() == nullptr) { - LOG(FATAL) << "Could not load " << class_name; - } - } - BindFunctionsOnClass(jenv, env, klass.get()); -} - -void BindFunctionsOnClass(jvmtiEnv* jenv, JNIEnv* env, jclass klass) { - // Use JVMTI to get the methods. - jint method_count; - jmethodID* methods; - jvmtiError methods_result = jenv->GetClassMethods(klass, &method_count, &methods); - if (methods_result != JVMTI_ERROR_NONE) { - LOG(FATAL) << "Could not get methods"; - } - - // Check each method. - for (jint i = 0; i < method_count; ++i) { - jint modifiers; - jvmtiError mod_result = jenv->GetMethodModifiers(methods[i], &modifiers); - if (mod_result != JVMTI_ERROR_NONE) { - LOG(FATAL) << "Could not get methods"; - } - constexpr jint kNative = static_cast<jint>(kAccNative); - if ((modifiers & kNative) != 0) { - BindMethod(jenv, env, klass, methods[i]); - } - } - - jenv->Deallocate(reinterpret_cast<unsigned char*>(methods)); -} - } // namespace art diff --git a/test/ti-agent/common_helper.h b/test/ti-agent/common_helper.h index f10356dcbb..610019e4d2 100644 --- a/test/ti-agent/common_helper.h +++ b/test/ti-agent/common_helper.h @@ -19,13 +19,11 @@ #include "jni.h" #include "jvmti.h" -#include "ScopedLocalRef.h" namespace art { -namespace common_redefine { +namespace common_redefine { jint OnLoad(JavaVM* vm, char* options, void* reserved); - } // namespace common_redefine namespace common_retransform { @@ -36,53 +34,6 @@ namespace common_transform { jint OnLoad(JavaVM* vm, char* options, void* reserved); } // namespace common_transform - -extern bool RuntimeIsJVM; - -bool IsJVM(); - -template <typename T> -static jobjectArray CreateObjectArray(JNIEnv* env, - jint length, - const char* component_type_descriptor, - T src) { - if (length < 0) { - return nullptr; - } - - ScopedLocalRef<jclass> obj_class(env, env->FindClass(component_type_descriptor)); - if (obj_class.get() == nullptr) { - return nullptr; - } - - ScopedLocalRef<jobjectArray> ret(env, env->NewObjectArray(length, obj_class.get(), nullptr)); - if (ret.get() == nullptr) { - return nullptr; - } - - for (jint i = 0; i < length; ++i) { - jobject element = src(i); - env->SetObjectArrayElement(ret.get(), static_cast<jint>(i), element); - env->DeleteLocalRef(element); - if (env->ExceptionCheck()) { - return nullptr; - } - } - - return ret.release(); -} - -void SetAllCapabilities(jvmtiEnv* env); - -bool JvmtiErrorToException(JNIEnv* env, jvmtiError error); - -// Load the class through JNI. Inspect it, find all native methods. Construct the corresponding -// mangled name, run dlsym and bind the method. -// -// This will abort on failure. -void BindFunctions(jvmtiEnv* jvmti_env, JNIEnv* env, const char* class_name); -void BindFunctionsOnClass(jvmtiEnv* jvmti_env, JNIEnv* env, jclass klass); - } // namespace art #endif // ART_TEST_TI_AGENT_COMMON_HELPER_H_ diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 303e8244da..c5d75c9468 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -14,15 +14,15 @@ * limitations under the License. */ -#include "common_load.h" - #include <jni.h> #include <stdio.h> -#include "art_method-inl.h" #include "base/logging.h" #include "base/macros.h" #include "common_helper.h" +#include "jni_binder.h" +#include "jvmti_helper.h" +#include "test_env.h" #include "901-hello-ti-agent/basics.h" #include "909-attach-agent/attach.h" @@ -31,8 +31,6 @@ namespace art { -jvmtiEnv* jvmti_env; - namespace { using OnLoad = jint (*)(JavaVM* vm, char* options, void* reserved); @@ -154,8 +152,8 @@ static bool FindAgentNameAndOptions(char* options, return true; } -static void SetIsJVM(char* options) { - RuntimeIsJVM = strncmp(options, "jvm", 3) == 0; +static void SetIsJVM(const char* options) { + SetJVM(strncmp(options, "jvm", 3) == 0); } static bool BindFunctionsAttached(JavaVM* vm, const char* class_name) { diff --git a/test/ti-agent/jni_binder.cc b/test/ti-agent/jni_binder.cc new file mode 100644 index 0000000000..efc2af81b1 --- /dev/null +++ b/test/ti-agent/jni_binder.cc @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jni_binder.h" + +#include <dlfcn.h> +#include <inttypes.h> +#include <stdio.h> + +#include "android-base/logging.h" +#include "android-base/stringprintf.h" + +#include "jvmti_helper.h" +#include "scoped_local_ref.h" +#include "scoped_utf_chars.h" + +namespace art { + +size_t CountModifiedUtf8Chars(const char* utf8, size_t byte_count) { + DCHECK_LE(byte_count, strlen(utf8)); + size_t len = 0; + const char* end = utf8 + byte_count; + for (; utf8 < end; ++utf8) { + int ic = *utf8; + len++; + if (LIKELY((ic & 0x80) == 0)) { + // One-byte encoding. + continue; + } + // Two- or three-byte encoding. + utf8++; + if ((ic & 0x20) == 0) { + // Two-byte encoding. + continue; + } + utf8++; + if ((ic & 0x10) == 0) { + // Three-byte encoding. + continue; + } + + // Four-byte encoding: needs to be converted into a surrogate + // pair. + utf8++; + len++; + } + return len; +} + +static uint16_t GetTrailingUtf16Char(uint32_t maybe_pair) { + return static_cast<uint16_t>(maybe_pair >> 16); +} + +static uint16_t GetLeadingUtf16Char(uint32_t maybe_pair) { + return static_cast<uint16_t>(maybe_pair & 0x0000FFFF); +} + +static uint32_t GetUtf16FromUtf8(const char** utf8_data_in) { + const uint8_t one = *(*utf8_data_in)++; + if ((one & 0x80) == 0) { + // one-byte encoding + return one; + } + + const uint8_t two = *(*utf8_data_in)++; + if ((one & 0x20) == 0) { + // two-byte encoding + return ((one & 0x1f) << 6) | (two & 0x3f); + } + + const uint8_t three = *(*utf8_data_in)++; + if ((one & 0x10) == 0) { + return ((one & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f); + } + + // Four byte encodings need special handling. We'll have + // to convert them into a surrogate pair. + const uint8_t four = *(*utf8_data_in)++; + + // Since this is a 4 byte UTF-8 sequence, it will lie between + // U+10000 and U+1FFFFF. + // + // TODO: What do we do about values in (U+10FFFF, U+1FFFFF) ? The + // spec says they're invalid but nobody appears to check for them. + const uint32_t code_point = ((one & 0x0f) << 18) | ((two & 0x3f) << 12) + | ((three & 0x3f) << 6) | (four & 0x3f); + + uint32_t surrogate_pair = 0; + // Step two: Write out the high (leading) surrogate to the bottom 16 bits + // of the of the 32 bit type. + surrogate_pair |= ((code_point >> 10) + 0xd7c0) & 0xffff; + // Step three : Write out the low (trailing) surrogate to the top 16 bits. + surrogate_pair |= ((code_point & 0x03ff) + 0xdc00) << 16; + + return surrogate_pair; +} + +static std::string MangleForJni(const std::string& s) { + std::string result; + size_t char_count = CountModifiedUtf8Chars(s.c_str(), s.length()); + const char* cp = &s[0]; + for (size_t i = 0; i < char_count; ++i) { + uint32_t ch = GetUtf16FromUtf8(&cp); + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) { + result.push_back(ch); + } else if (ch == '.' || ch == '/') { + result += "_"; + } else if (ch == '_') { + result += "_1"; + } else if (ch == ';') { + result += "_2"; + } else if (ch == '[') { + result += "_3"; + } else { + const uint16_t leading = GetLeadingUtf16Char(ch); + const uint32_t trailing = GetTrailingUtf16Char(ch); + + android::base::StringAppendF(&result, "_0%04x", leading); + if (trailing != 0) { + android::base::StringAppendF(&result, "_0%04x", trailing); + } + } + } + return result; +} + +static std::string GetJniShortName(const std::string& class_descriptor, const std::string& method) { + // Remove the leading 'L' and trailing ';'... + std::string class_name(class_descriptor); + CHECK_EQ(class_name[0], 'L') << class_name; + CHECK_EQ(class_name[class_name.size() - 1], ';') << class_name; + class_name.erase(0, 1); + class_name.erase(class_name.size() - 1, 1); + + std::string short_name; + short_name += "Java_"; + short_name += MangleForJni(class_name); + short_name += "_"; + short_name += MangleForJni(method); + return short_name; +} + +static void BindMethod(jvmtiEnv* jvmti_env, JNIEnv* env, jclass klass, jmethodID method) { + std::string name; + std::string signature; + std::string mangled_names[2]; + { + char* name_cstr; + char* sig_cstr; + jvmtiError name_result = jvmti_env->GetMethodName(method, &name_cstr, &sig_cstr, nullptr); + CheckJvmtiError(jvmti_env, name_result); + CHECK(name_cstr != nullptr); + CHECK(sig_cstr != nullptr); + name = name_cstr; + signature = sig_cstr; + + char* klass_name; + jvmtiError klass_result = jvmti_env->GetClassSignature(klass, &klass_name, nullptr); + CheckJvmtiError(jvmti_env, klass_result); + + mangled_names[0] = GetJniShortName(klass_name, name); + // TODO: Long JNI name. + + CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, name_cstr)); + CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, sig_cstr)); + CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, klass_name)); + } + + for (const std::string& mangled_name : mangled_names) { + if (mangled_name.empty()) { + continue; + } + void* sym = dlsym(RTLD_DEFAULT, mangled_name.c_str()); + if (sym == nullptr) { + continue; + } + + JNINativeMethod native_method; + native_method.fnPtr = sym; + native_method.name = name.c_str(); + native_method.signature = signature.c_str(); + + env->RegisterNatives(klass, &native_method, 1); + + return; + } + + LOG(FATAL) << "Could not find " << mangled_names[0]; +} + +static std::string DescriptorToDot(const char* descriptor) { + size_t length = strlen(descriptor); + if (length > 1) { + if (descriptor[0] == 'L' && descriptor[length - 1] == ';') { + // Descriptors have the leading 'L' and trailing ';' stripped. + std::string result(descriptor + 1, length - 2); + std::replace(result.begin(), result.end(), '/', '.'); + return result; + } else { + // For arrays the 'L' and ';' remain intact. + std::string result(descriptor); + std::replace(result.begin(), result.end(), '/', '.'); + return result; + } + } + // Do nothing for non-class/array descriptors. + return descriptor; +} + +static jobject GetSystemClassLoader(JNIEnv* env) { + ScopedLocalRef<jclass> cl_klass(env, env->FindClass("java/lang/ClassLoader")); + CHECK(cl_klass.get() != nullptr); + jmethodID getsystemclassloader_method = env->GetStaticMethodID(cl_klass.get(), + "getSystemClassLoader", + "()Ljava/lang/ClassLoader;"); + CHECK(getsystemclassloader_method != nullptr); + return env->CallStaticObjectMethod(cl_klass.get(), getsystemclassloader_method); +} + +static jclass FindClassWithClassLoader(JNIEnv* env, const char* class_name, jobject class_loader) { + // Create a String of the name. + std::string descriptor = android::base::StringPrintf("L%s;", class_name); + std::string dot_name = DescriptorToDot(descriptor.c_str()); + ScopedLocalRef<jstring> name_str(env, env->NewStringUTF(dot_name.c_str())); + + // Call Class.forName with it. + ScopedLocalRef<jclass> c_klass(env, env->FindClass("java/lang/Class")); + CHECK(c_klass.get() != nullptr); + jmethodID forname_method = env->GetStaticMethodID( + c_klass.get(), + "forName", + "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"); + CHECK(forname_method != nullptr); + + return static_cast<jclass>(env->CallStaticObjectMethod(c_klass.get(), + forname_method, + name_str.get(), + JNI_FALSE, + class_loader)); +} + +// Find the given classname. First try the implied classloader, then the system classloader, +// then use JVMTI to find all classloaders. +static jclass FindClass(jvmtiEnv* jvmti_env, + JNIEnv* env, + const char* class_name, + jobject class_loader) { + if (class_loader != nullptr) { + return FindClassWithClassLoader(env, class_name, class_loader); + } + + jclass from_implied = env->FindClass(class_name); + if (from_implied != nullptr) { + return from_implied; + } + env->ExceptionClear(); + + ScopedLocalRef<jobject> system_class_loader(env, GetSystemClassLoader(env)); + CHECK(system_class_loader.get() != nullptr); + jclass from_system = FindClassWithClassLoader(env, class_name, system_class_loader.get()); + if (from_system != nullptr) { + return from_system; + } + env->ExceptionClear(); + + // Look at the context classloaders of all threads. + jint thread_count; + jthread* threads; + CheckJvmtiError(jvmti_env, jvmti_env->GetAllThreads(&thread_count, &threads)); + JvmtiUniquePtr threads_uptr = MakeJvmtiUniquePtr(jvmti_env, threads); + + jclass result = nullptr; + for (jint t = 0; t != thread_count; ++t) { + // Always loop over all elements, as we need to free the local references. + if (result == nullptr) { + jvmtiThreadInfo info; + CheckJvmtiError(jvmti_env, jvmti_env->GetThreadInfo(threads[t], &info)); + CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, info.name)); + if (info.thread_group != nullptr) { + env->DeleteLocalRef(info.thread_group); + } + if (info.context_class_loader != nullptr) { + result = FindClassWithClassLoader(env, class_name, info.context_class_loader); + env->ExceptionClear(); + env->DeleteLocalRef(info.context_class_loader); + } + } + env->DeleteLocalRef(threads[t]); + } + + if (result != nullptr) { + return result; + } + + // TODO: Implement scanning *all* classloaders. + LOG(FATAL) << "Unimplemented"; + + return nullptr; +} + +void BindFunctionsOnClass(jvmtiEnv* jvmti_env, JNIEnv* env, jclass klass) { + // Use JVMTI to get the methods. + jint method_count; + jmethodID* methods; + jvmtiError methods_result = jvmti_env->GetClassMethods(klass, &method_count, &methods); + CheckJvmtiError(jvmti_env, methods_result); + + // Check each method. + for (jint i = 0; i < method_count; ++i) { + jint modifiers; + jvmtiError mod_result = jvmti_env->GetMethodModifiers(methods[i], &modifiers); + CheckJvmtiError(jvmti_env, mod_result); + constexpr jint kNative = static_cast<jint>(0x0100); + if ((modifiers & kNative) != 0) { + BindMethod(jvmti_env, env, klass, methods[i]); + } + } + + CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, methods)); +} + +void BindFunctions(jvmtiEnv* jvmti_env, JNIEnv* env, const char* class_name, jobject class_loader) { + // Use JNI to load the class. + ScopedLocalRef<jclass> klass(env, FindClass(jvmti_env, env, class_name, class_loader)); + CHECK(klass.get() != nullptr) << class_name; + BindFunctionsOnClass(jvmti_env, env, klass.get()); +} + +} // namespace art diff --git a/test/ti-agent/jni_binder.h b/test/ti-agent/jni_binder.h new file mode 100644 index 0000000000..6f96257c75 --- /dev/null +++ b/test/ti-agent/jni_binder.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_TI_AGENT_JNI_BINDER_H_ +#define ART_TEST_TI_AGENT_JNI_BINDER_H_ + +#include "jni.h" +#include "jvmti.h" + +namespace art { + +// Load the class through JNI. Inspect it, find all native methods. Construct the corresponding +// mangled name, run dlsym and bind the method. +// +// This will abort on failure. +void BindFunctions(jvmtiEnv* jvmti_env, + JNIEnv* env, + const char* class_name, + jobject class_loader = nullptr); + +void BindFunctionsOnClass(jvmtiEnv* jvmti_env, JNIEnv* env, jclass klass); + +} // namespace art + +#endif // ART_TEST_TI_AGENT_JNI_BINDER_H_ diff --git a/test/ti-agent/jni_helper.h b/test/ti-agent/jni_helper.h new file mode 100644 index 0000000000..c48b0c0c4f --- /dev/null +++ b/test/ti-agent/jni_helper.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_TI_AGENT_JNI_HELPER_H_ +#define ART_TEST_TI_AGENT_JNI_HELPER_H_ + +#include "jni.h" +#include "scoped_local_ref.h" + +namespace art { + +// Create an object array using a lambda that returns a local ref for each element. +template <typename T> +static inline jobjectArray CreateObjectArray(JNIEnv* env, + jint length, + const char* component_type_descriptor, + T src) { + if (length < 0) { + return nullptr; + } + + ScopedLocalRef<jclass> obj_class(env, env->FindClass(component_type_descriptor)); + if (obj_class.get() == nullptr) { + return nullptr; + } + + ScopedLocalRef<jobjectArray> ret(env, env->NewObjectArray(length, obj_class.get(), nullptr)); + if (ret.get() == nullptr) { + return nullptr; + } + + for (jint i = 0; i < length; ++i) { + jobject element = src(i); + env->SetObjectArrayElement(ret.get(), static_cast<jint>(i), element); + env->DeleteLocalRef(element); + if (env->ExceptionCheck()) { + return nullptr; + } + } + + return ret.release(); +} + +} // namespace art + +#endif // ART_TEST_TI_AGENT_JNI_HELPER_H_ diff --git a/test/ti-agent/jvmti_helper.cc b/test/ti-agent/jvmti_helper.cc new file mode 100644 index 0000000000..598a30f940 --- /dev/null +++ b/test/ti-agent/jvmti_helper.cc @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jvmti_helper.h" + +#include <algorithm> +#include <dlfcn.h> +#include <stdio.h> +#include <sstream> +#include <string.h> + +#include "android-base/logging.h" +#include "scoped_local_ref.h" + +namespace art { + +void CheckJvmtiError(jvmtiEnv* env, jvmtiError error) { + if (error != JVMTI_ERROR_NONE) { + char* error_name; + jvmtiError name_error = env->GetErrorName(error, &error_name); + if (name_error != JVMTI_ERROR_NONE) { + LOG(FATAL) << "Unable to get error name for " << error; + } + LOG(FATAL) << "Unexpected error: " << error_name; + } +} + +void SetAllCapabilities(jvmtiEnv* env) { + jvmtiCapabilities caps; + jvmtiError error1 = env->GetPotentialCapabilities(&caps); + CheckJvmtiError(env, error1); + jvmtiError error2 = env->AddCapabilities(&caps); + CheckJvmtiError(env, error2); +} + +bool JvmtiErrorToException(JNIEnv* env, jvmtiEnv* jvmti_env, jvmtiError error) { + if (error == JVMTI_ERROR_NONE) { + return false; + } + + ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); + if (rt_exception.get() == nullptr) { + // CNFE should be pending. + return true; + } + + char* err; + CheckJvmtiError(jvmti_env, jvmti_env->GetErrorName(error, &err)); + + env->ThrowNew(rt_exception.get(), err); + + Deallocate(jvmti_env, err); + return true; +} + +std::ostream& operator<<(std::ostream& os, const jvmtiError& rhs) { + switch (rhs) { + case JVMTI_ERROR_NONE: + return os << "NONE"; + case JVMTI_ERROR_INVALID_THREAD: + return os << "INVALID_THREAD"; + case JVMTI_ERROR_INVALID_THREAD_GROUP: + return os << "INVALID_THREAD_GROUP"; + case JVMTI_ERROR_INVALID_PRIORITY: + return os << "INVALID_PRIORITY"; + case JVMTI_ERROR_THREAD_NOT_SUSPENDED: + return os << "THREAD_NOT_SUSPENDED"; + case JVMTI_ERROR_THREAD_SUSPENDED: + return os << "THREAD_SUSPENDED"; + case JVMTI_ERROR_THREAD_NOT_ALIVE: + return os << "THREAD_NOT_ALIVE"; + case JVMTI_ERROR_INVALID_OBJECT: + return os << "INVALID_OBJECT"; + case JVMTI_ERROR_INVALID_CLASS: + return os << "INVALID_CLASS"; + case JVMTI_ERROR_CLASS_NOT_PREPARED: + return os << "CLASS_NOT_PREPARED"; + case JVMTI_ERROR_INVALID_METHODID: + return os << "INVALID_METHODID"; + case JVMTI_ERROR_INVALID_LOCATION: + return os << "INVALID_LOCATION"; + case JVMTI_ERROR_INVALID_FIELDID: + return os << "INVALID_FIELDID"; + case JVMTI_ERROR_NO_MORE_FRAMES: + return os << "NO_MORE_FRAMES"; + case JVMTI_ERROR_OPAQUE_FRAME: + return os << "OPAQUE_FRAME"; + case JVMTI_ERROR_TYPE_MISMATCH: + return os << "TYPE_MISMATCH"; + case JVMTI_ERROR_INVALID_SLOT: + return os << "INVALID_SLOT"; + case JVMTI_ERROR_DUPLICATE: + return os << "DUPLICATE"; + case JVMTI_ERROR_NOT_FOUND: + return os << "NOT_FOUND"; + case JVMTI_ERROR_INVALID_MONITOR: + return os << "INVALID_MONITOR"; + case JVMTI_ERROR_NOT_MONITOR_OWNER: + return os << "NOT_MONITOR_OWNER"; + case JVMTI_ERROR_INTERRUPT: + return os << "INTERRUPT"; + case JVMTI_ERROR_INVALID_CLASS_FORMAT: + return os << "INVALID_CLASS_FORMAT"; + case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION: + return os << "CIRCULAR_CLASS_DEFINITION"; + case JVMTI_ERROR_FAILS_VERIFICATION: + return os << "FAILS_VERIFICATION"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED: + return os << "UNSUPPORTED_REDEFINITION_METHOD_ADDED"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED: + return os << "UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED"; + case JVMTI_ERROR_INVALID_TYPESTATE: + return os << "INVALID_TYPESTATE"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED: + return os << "UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED: + return os << "UNSUPPORTED_REDEFINITION_METHOD_DELETED"; + case JVMTI_ERROR_UNSUPPORTED_VERSION: + return os << "UNSUPPORTED_VERSION"; + case JVMTI_ERROR_NAMES_DONT_MATCH: + return os << "NAMES_DONT_MATCH"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED: + return os << "UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED"; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED: + return os << "UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED"; + case JVMTI_ERROR_UNMODIFIABLE_CLASS: + return os << "JVMTI_ERROR_UNMODIFIABLE_CLASS"; + case JVMTI_ERROR_NOT_AVAILABLE: + return os << "NOT_AVAILABLE"; + case JVMTI_ERROR_MUST_POSSESS_CAPABILITY: + return os << "MUST_POSSESS_CAPABILITY"; + case JVMTI_ERROR_NULL_POINTER: + return os << "NULL_POINTER"; + case JVMTI_ERROR_ABSENT_INFORMATION: + return os << "ABSENT_INFORMATION"; + case JVMTI_ERROR_INVALID_EVENT_TYPE: + return os << "INVALID_EVENT_TYPE"; + case JVMTI_ERROR_ILLEGAL_ARGUMENT: + return os << "ILLEGAL_ARGUMENT"; + case JVMTI_ERROR_NATIVE_METHOD: + return os << "NATIVE_METHOD"; + case JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED: + return os << "CLASS_LOADER_UNSUPPORTED"; + case JVMTI_ERROR_OUT_OF_MEMORY: + return os << "OUT_OF_MEMORY"; + case JVMTI_ERROR_ACCESS_DENIED: + return os << "ACCESS_DENIED"; + case JVMTI_ERROR_WRONG_PHASE: + return os << "WRONG_PHASE"; + case JVMTI_ERROR_INTERNAL: + return os << "INTERNAL"; + case JVMTI_ERROR_UNATTACHED_THREAD: + return os << "UNATTACHED_THREAD"; + case JVMTI_ERROR_INVALID_ENVIRONMENT: + return os << "INVALID_ENVIRONMENT"; + } + LOG(FATAL) << "Unexpected error type " << static_cast<int>(rhs); + __builtin_unreachable(); +} + +} // namespace art diff --git a/test/ti-agent/jvmti_helper.h b/test/ti-agent/jvmti_helper.h new file mode 100644 index 0000000000..66d88d0752 --- /dev/null +++ b/test/ti-agent/jvmti_helper.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_TI_AGENT_JVMTI_HELPER_H_ +#define ART_TEST_TI_AGENT_JVMTI_HELPER_H_ + +#include "jni.h" +#include "jvmti.h" +#include <memory> +#include <ostream> + +#include "android-base/logging.h" + +namespace art { + +// Add all capabilities to the given env. +void SetAllCapabilities(jvmtiEnv* env); + +// Check whether the given error is NONE. If not, print out the corresponding error message +// and abort. +void CheckJvmtiError(jvmtiEnv* env, jvmtiError error); + +// Convert the given error to a RuntimeException with a message derived from the error. Returns +// true on error, false if error is JVMTI_ERROR_NONE. +bool JvmtiErrorToException(JNIEnv* env, jvmtiEnv* jvmti_env, jvmtiError error); + +class JvmtiDeleter { + public: + JvmtiDeleter() : env_(nullptr) {} + explicit JvmtiDeleter(jvmtiEnv* env) : env_(env) {} + + JvmtiDeleter(JvmtiDeleter&) = default; + JvmtiDeleter(JvmtiDeleter&&) = default; + JvmtiDeleter& operator=(const JvmtiDeleter&) = default; + + void operator()(unsigned char* ptr) const { + CHECK(env_ != nullptr); + jvmtiError ret = env_->Deallocate(ptr); + CheckJvmtiError(env_, ret); + } + + private: + mutable jvmtiEnv* env_; +}; + +using JvmtiUniquePtr = std::unique_ptr<unsigned char, JvmtiDeleter>; + +template <typename T> +static inline JvmtiUniquePtr MakeJvmtiUniquePtr(jvmtiEnv* env, T* mem) { + return JvmtiUniquePtr(reinterpret_cast<unsigned char*>(mem), JvmtiDeleter(env)); +} + +template <typename T> +static inline jvmtiError Deallocate(jvmtiEnv* env, T* mem) { + return env->Deallocate(reinterpret_cast<unsigned char*>(mem)); +} + +// To print jvmtiError. Does not rely on GetErrorName, so is an approximation. +std::ostream& operator<<(std::ostream& os, const jvmtiError& rhs); + +} // namespace art + +#endif // ART_TEST_TI_AGENT_JVMTI_HELPER_H_ diff --git a/test/ti-agent/scoped_local_ref.h b/test/ti-agent/scoped_local_ref.h new file mode 100644 index 0000000000..0cd9891199 --- /dev/null +++ b/test/ti-agent/scoped_local_ref.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_TI_AGENT_SCOPED_LOCAL_REF_H_ +#define ART_TEST_TI_AGENT_SCOPED_LOCAL_REF_H_ + +#include "jni.h" + +#include <stddef.h> + +#include "android-base/macros.h" + +namespace art { + +template<typename T> +class ScopedLocalRef { + public: + ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) { + } + + ~ScopedLocalRef() { + reset(); + } + + void reset(T ptr = NULL) { + if (ptr != mLocalRef) { + if (mLocalRef != NULL) { + mEnv->DeleteLocalRef(mLocalRef); + } + mLocalRef = ptr; + } + } + + T release() __attribute__((warn_unused_result)) { + T localRef = mLocalRef; + mLocalRef = NULL; + return localRef; + } + + T get() const { + return mLocalRef; + } + + private: + JNIEnv* const mEnv; + T mLocalRef; + + DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef); +}; + +} // namespace art + +#endif // ART_TEST_TI_AGENT_SCOPED_LOCAL_REF_H_ diff --git a/test/ti-agent/scoped_utf_chars.h b/test/ti-agent/scoped_utf_chars.h new file mode 100644 index 0000000000..e8c9a11539 --- /dev/null +++ b/test/ti-agent/scoped_utf_chars.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_TEST_TI_AGENT_SCOPED_UTF_CHARS_H_ +#define ART_TEST_TI_AGENT_SCOPED_UTF_CHARS_H_ + +#include "jni.h" + +#include <string.h> + +#include "android-base/macros.h" + +namespace art { + +class ScopedUtfChars { + public: + ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) { + if (s == nullptr) { + utf_chars_ = nullptr; + // TODO: JniThrowNullPointerException(env, nullptr); + } else { + utf_chars_ = env->GetStringUTFChars(s, nullptr); + } + } + + ScopedUtfChars(ScopedUtfChars&& rhs) : + env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) { + rhs.env_ = nullptr; + rhs.string_ = nullptr; + rhs.utf_chars_ = nullptr; + } + + ~ScopedUtfChars() { + if (utf_chars_) { + env_->ReleaseStringUTFChars(string_, utf_chars_); + } + } + + ScopedUtfChars& operator=(ScopedUtfChars&& rhs) { + if (this != &rhs) { + // Delete the currently owned UTF chars. + this->~ScopedUtfChars(); + + // Move the rhs ScopedUtfChars and zero it out. + env_ = rhs.env_; + string_ = rhs.string_; + utf_chars_ = rhs.utf_chars_; + rhs.env_ = nullptr; + rhs.string_ = nullptr; + rhs.utf_chars_ = nullptr; + } + return *this; + } + + const char* c_str() const { + return utf_chars_; + } + + size_t size() const { + return strlen(utf_chars_); + } + + const char& operator[](size_t n) const { + return utf_chars_[n]; + } + + private: + JNIEnv* env_; + jstring string_; + const char* utf_chars_; + + DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars); +}; + +} // namespace art + +#endif // ART_TEST_TI_AGENT_SCOPED_UTF_CHARS_H_ diff --git a/test/ti-agent/test_env.cc b/test/ti-agent/test_env.cc new file mode 100644 index 0000000000..cf47f22b03 --- /dev/null +++ b/test/ti-agent/test_env.cc @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test_env.h" + +namespace art { + +jvmtiEnv* jvmti_env = nullptr; + +static bool gRuntimeIsJVM = false; + +bool IsJVM() { + return gRuntimeIsJVM; +} + +void SetJVM(bool b) { + gRuntimeIsJVM = b; +} + +} // namespace art diff --git a/test/ti-agent/common_load.h b/test/ti-agent/test_env.h index e79a0067b0..2eb631c36c 100644 --- a/test/ti-agent/common_load.h +++ b/test/ti-agent/test_env.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_TEST_TI_AGENT_COMMON_LOAD_H_ -#define ART_TEST_TI_AGENT_COMMON_LOAD_H_ +#ifndef ART_TEST_TI_AGENT_TEST_ENV_H_ +#define ART_TEST_TI_AGENT_TEST_ENV_H_ #include "jvmti.h" @@ -23,6 +23,9 @@ namespace art { extern jvmtiEnv* jvmti_env; +bool IsJVM(); +void SetJVM(bool b); + } // namespace art -#endif // ART_TEST_TI_AGENT_COMMON_LOAD_H_ +#endif // ART_TEST_TI_AGENT_TEST_ENV_H_ |