diff options
-rw-r--r-- | runtime/openjdkjvmti/OpenjdkJvmTi.cc | 161 | ||||
-rw-r--r-- | test/901-hello-ti-agent/basics.cc | 16 | ||||
-rw-r--r-- | test/901-hello-ti-agent/expected.txt | 1 | ||||
-rw-r--r-- | test/901-hello-ti-agent/src/Main.java | 4 |
4 files changed, 167 insertions, 15 deletions
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index 5401e5cdf8..735b4c01fa 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -79,20 +79,26 @@ EventHandler gEventHandler; class JvmtiFunctions { private: - static bool IsValidEnv(jvmtiEnv* env) { - return env != nullptr; + static jvmtiError getEnvironmentError(jvmtiEnv* env) { + if (env == nullptr) { + return ERR(INVALID_ENVIRONMENT); + } else if (art::Thread::Current() == nullptr) { + return ERR(UNATTACHED_THREAD); + } else { + return OK; + } } -#define ENSURE_VALID_ENV(env) \ - do { \ - if (!IsValidEnv(env)) { \ - return ERR(INVALID_ENVIRONMENT); \ - } \ +#define ENSURE_VALID_ENV(env) \ + do { \ + jvmtiError ensure_valid_env_ ## __LINE__ = getEnvironmentError(env); \ + if (ensure_valid_env_ ## __LINE__ != OK) { \ + return ensure_valid_env_ ## __LINE__ ; \ + } \ } while (false) #define ENSURE_HAS_CAP(env, cap) \ do { \ - ENSURE_VALID_ENV(env); \ if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.cap != 1) { \ return ERR(MUST_POSSESS_CAPABILITY); \ } \ @@ -121,18 +127,22 @@ class JvmtiFunctions { } static jvmtiError GetThreadState(jvmtiEnv* env, jthread thread, jint* thread_state_ptr) { + ENSURE_VALID_ENV(env); return ThreadUtil::GetThreadState(env, thread, thread_state_ptr); } static jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr) { + ENSURE_VALID_ENV(env); return ThreadUtil::GetCurrentThread(env, thread_ptr); } static jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr) { + ENSURE_VALID_ENV(env); return ThreadUtil::GetAllThreads(env, threads_count_ptr, threads_ptr); } static jvmtiError SuspendThread(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_suspend); return ERR(NOT_IMPLEMENTED); } @@ -141,11 +151,13 @@ class JvmtiFunctions { jint request_count ATTRIBUTE_UNUSED, const jthread* request_list ATTRIBUTE_UNUSED, jvmtiError* results ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_suspend); return ERR(NOT_IMPLEMENTED); } static jvmtiError ResumeThread(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_suspend); return ERR(NOT_IMPLEMENTED); } @@ -154,6 +166,7 @@ class JvmtiFunctions { jint request_count ATTRIBUTE_UNUSED, const jthread* request_list ATTRIBUTE_UNUSED, jvmtiError* results ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_suspend); return ERR(NOT_IMPLEMENTED); } @@ -161,16 +174,19 @@ class JvmtiFunctions { static jvmtiError StopThread(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jobject exception ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_signal_thread); return ERR(NOT_IMPLEMENTED); } static jvmtiError InterruptThread(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_signal_thread); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) { + ENSURE_VALID_ENV(env); return ThreadUtil::GetThreadInfo(env, thread, info_ptr); } @@ -178,6 +194,7 @@ class JvmtiFunctions { jthread thread ATTRIBUTE_UNUSED, jint* owned_monitor_count_ptr ATTRIBUTE_UNUSED, jobject** owned_monitors_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_owned_monitor_info); return ERR(NOT_IMPLEMENTED); } @@ -187,6 +204,7 @@ class JvmtiFunctions { jthread thread ATTRIBUTE_UNUSED, jint* monitor_info_count_ptr ATTRIBUTE_UNUSED, jvmtiMonitorStackDepthInfo** monitor_info_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_owned_monitor_stack_depth_info); return ERR(NOT_IMPLEMENTED); } @@ -194,6 +212,7 @@ class JvmtiFunctions { static jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jobject* monitor_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_current_contended_monitor); return ERR(NOT_IMPLEMENTED); } @@ -203,26 +222,31 @@ class JvmtiFunctions { jvmtiStartFunction proc, const void* arg, jint priority) { + ENSURE_VALID_ENV(env); return ThreadUtil::RunAgentThread(env, thread, proc, arg, priority); } static jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data) { + ENSURE_VALID_ENV(env); return ThreadUtil::SetThreadLocalStorage(env, thread, data); } static jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr) { + ENSURE_VALID_ENV(env); return ThreadUtil::GetThreadLocalStorage(env, thread, data_ptr); } static jvmtiError GetTopThreadGroups(jvmtiEnv* env, jint* group_count_ptr, jthreadGroup** groups_ptr) { + ENSURE_VALID_ENV(env); return ThreadGroupUtil::GetTopThreadGroups(env, group_count_ptr, groups_ptr); } static jvmtiError GetThreadGroupInfo(jvmtiEnv* env, jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) { + ENSURE_VALID_ENV(env); return ThreadGroupUtil::GetThreadGroupInfo(env, group, info_ptr); } @@ -232,6 +256,7 @@ class JvmtiFunctions { jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr) { + ENSURE_VALID_ENV(env); return ThreadGroupUtil::GetThreadGroupChildren(env, group, thread_count_ptr, @@ -246,6 +271,7 @@ class JvmtiFunctions { jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) { + ENSURE_VALID_ENV(env); return StackUtil::GetStackTrace(env, thread, start_depth, @@ -258,6 +284,7 @@ class JvmtiFunctions { jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) { + ENSURE_VALID_ENV(env); return StackUtil::GetAllStackTraces(env, max_frame_count, stack_info_ptr, thread_count_ptr); } @@ -266,6 +293,7 @@ class JvmtiFunctions { const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr) { + ENSURE_VALID_ENV(env); return StackUtil::GetThreadListStackTraces(env, thread_count, thread_list, @@ -274,10 +302,12 @@ class JvmtiFunctions { } static jvmtiError GetFrameCount(jvmtiEnv* env, jthread thread, jint* count_ptr) { + ENSURE_VALID_ENV(env); return StackUtil::GetFrameCount(env, thread, count_ptr); } static jvmtiError PopFrame(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_pop_frame); return ERR(NOT_IMPLEMENTED); } @@ -287,12 +317,14 @@ class JvmtiFunctions { jint depth, jmethodID* method_ptr, jlocation* location_ptr) { + ENSURE_VALID_ENV(env); return StackUtil::GetFrameLocation(env, thread, depth, method_ptr, location_ptr); } static jvmtiError NotifyFramePop(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jint depth ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_frame_pop_events); return ERR(NOT_IMPLEMENTED); } @@ -300,6 +332,7 @@ class JvmtiFunctions { static jvmtiError ForceEarlyReturnObject(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jobject value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } @@ -307,6 +340,7 @@ class JvmtiFunctions { static jvmtiError ForceEarlyReturnInt(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jint value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } @@ -314,6 +348,7 @@ class JvmtiFunctions { static jvmtiError ForceEarlyReturnLong(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jlong value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } @@ -321,6 +356,7 @@ class JvmtiFunctions { static jvmtiError ForceEarlyReturnFloat(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jfloat value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } @@ -328,11 +364,13 @@ class JvmtiFunctions { static jvmtiError ForceEarlyReturnDouble(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jdouble value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } static jvmtiError ForceEarlyReturnVoid(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_force_early_return); return ERR(NOT_IMPLEMENTED); } @@ -343,6 +381,7 @@ class JvmtiFunctions { jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get()); return heap_util.FollowReferences(env, @@ -358,12 +397,14 @@ class JvmtiFunctions { jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get()); return heap_util.IterateThroughHeap(env, heap_filter, klass, callbacks, user_data); } static jvmtiError GetTag(jvmtiEnv* env, jobject object, jlong* tag_ptr) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); JNIEnv* jni_env = GetJniEnv(env); @@ -381,6 +422,7 @@ class JvmtiFunctions { } static jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); if (object == nullptr) { @@ -405,6 +447,7 @@ class JvmtiFunctions { jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); JNIEnv* jni_env = GetJniEnv(env); @@ -422,6 +465,7 @@ class JvmtiFunctions { } static jvmtiError ForceGarbageCollection(jvmtiEnv* env) { + ENSURE_VALID_ENV(env); return HeapUtil::ForceGarbageCollection(env); } @@ -430,6 +474,7 @@ class JvmtiFunctions { jobject object ATTRIBUTE_UNUSED, jvmtiObjectReferenceCallback object_reference_callback ATTRIBUTE_UNUSED, const void* user_data ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); return ERR(NOT_IMPLEMENTED); } @@ -440,6 +485,7 @@ class JvmtiFunctions { jvmtiStackReferenceCallback stack_ref_callback ATTRIBUTE_UNUSED, jvmtiObjectReferenceCallback object_ref_callback ATTRIBUTE_UNUSED, const void* user_data ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); return ERR(NOT_IMPLEMENTED); } @@ -448,6 +494,7 @@ class JvmtiFunctions { jvmtiHeapObjectFilter object_filter ATTRIBUTE_UNUSED, jvmtiHeapObjectCallback heap_object_callback ATTRIBUTE_UNUSED, const void* user_data ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); return ERR(NOT_IMPLEMENTED); } @@ -458,6 +505,7 @@ class JvmtiFunctions { jvmtiHeapObjectFilter object_filter ATTRIBUTE_UNUSED, jvmtiHeapObjectCallback heap_object_callback ATTRIBUTE_UNUSED, const void* user_data ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_tag_objects); return ERR(NOT_IMPLEMENTED); } @@ -467,6 +515,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jobject* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -475,6 +524,7 @@ class JvmtiFunctions { jthread thread ATTRIBUTE_UNUSED, jint depth ATTRIBUTE_UNUSED, jobject* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -484,6 +534,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jint* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -493,6 +544,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jlong* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -502,6 +554,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jfloat* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -511,6 +564,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jdouble* value_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -520,6 +574,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jobject value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -529,6 +584,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jint value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -538,6 +594,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jlong value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -547,6 +604,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jfloat value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -556,6 +614,7 @@ class JvmtiFunctions { jint depth ATTRIBUTE_UNUSED, jint slot ATTRIBUTE_UNUSED, jdouble value ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -563,6 +622,7 @@ class JvmtiFunctions { static jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method ATTRIBUTE_UNUSED, jlocation location ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_breakpoint_events); return ERR(NOT_IMPLEMENTED); } @@ -570,6 +630,7 @@ class JvmtiFunctions { static jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method ATTRIBUTE_UNUSED, jlocation location ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_breakpoint_events); return ERR(NOT_IMPLEMENTED); } @@ -577,6 +638,7 @@ class JvmtiFunctions { static jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, jfieldID field ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_field_access_events); return ERR(NOT_IMPLEMENTED); } @@ -584,6 +646,7 @@ class JvmtiFunctions { static jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, jfieldID field ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_field_access_events); return ERR(NOT_IMPLEMENTED); } @@ -591,6 +654,7 @@ class JvmtiFunctions { static jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, jfieldID field ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_field_modification_events); return ERR(NOT_IMPLEMENTED); } @@ -598,11 +662,13 @@ class JvmtiFunctions { static jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, jfieldID field ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_generate_field_modification_events); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr) { + ENSURE_VALID_ENV(env); HeapUtil heap_util(ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get()); return heap_util.GetLoadedClasses(env, class_count_ptr, classes_ptr); } @@ -611,6 +677,7 @@ class JvmtiFunctions { jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassLoaderClasses(env, initiating_loader, class_count_ptr, classes_ptr); } @@ -618,21 +685,25 @@ class JvmtiFunctions { jclass klass, char** signature_ptr, char** generic_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassSignature(env, klass, signature_ptr, generic_ptr); } static jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassStatus(env, klass, status_ptr); } static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, char** source_name_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_source_file_name); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassModifiers(env, klass, modifiers_ptr); } @@ -640,6 +711,7 @@ class JvmtiFunctions { jclass klass, jint* method_count_ptr, jmethodID** methods_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassMethods(env, klass, method_count_ptr, methods_ptr); } @@ -647,6 +719,7 @@ class JvmtiFunctions { jclass klass, jint* field_count_ptr, jfieldID** fields_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassFields(env, klass, field_count_ptr, fields_ptr); } @@ -654,6 +727,7 @@ class JvmtiFunctions { jclass klass, jint* interface_count_ptr, jclass** interfaces_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetImplementedInterfaces(env, klass, interface_count_ptr, interfaces_ptr); } @@ -661,6 +735,7 @@ class JvmtiFunctions { jclass klass, jint* minor_version_ptr, jint* major_version_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassVersionNumbers(env, klass, minor_version_ptr, major_version_ptr); } @@ -669,38 +744,45 @@ class JvmtiFunctions { jint* constant_pool_count_ptr ATTRIBUTE_UNUSED, jint* constant_pool_byte_count_ptr ATTRIBUTE_UNUSED, unsigned char** constant_pool_bytes_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_constant_pool); return ERR(NOT_IMPLEMENTED); } static jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::IsInterface(env, klass, is_interface_ptr); } static jvmtiError IsArrayClass(jvmtiEnv* env, jclass klass, jboolean* is_array_class_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::IsArrayClass(env, klass, is_array_class_ptr); } static jvmtiError IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_modifiable_class_ptr) { + ENSURE_VALID_ENV(env); return Redefiner::IsModifiableClass(env, klass, is_modifiable_class_ptr); } static jvmtiError GetClassLoader(jvmtiEnv* env, jclass klass, jobject* classloader_ptr) { + ENSURE_VALID_ENV(env); return ClassUtil::GetClassLoader(env, klass, classloader_ptr); } static jvmtiError GetSourceDebugExtension(jvmtiEnv* env, jclass klass ATTRIBUTE_UNUSED, char** source_debug_extension_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_source_debug_extension); return ERR(NOT_IMPLEMENTED); } static jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_retransform_classes); std::string error_msg; jvmtiError res = Transformer::RetransformClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env), @@ -719,6 +801,7 @@ class JvmtiFunctions { static jvmtiError RedefineClasses(jvmtiEnv* env, jint class_count, const jvmtiClassDefinition* class_definitions) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_redefine_classes); std::string error_msg; jvmtiError res = Redefiner::RedefineClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env), @@ -735,16 +818,19 @@ class JvmtiFunctions { } static jvmtiError GetObjectSize(jvmtiEnv* env, jobject object, jlong* size_ptr) { + ENSURE_VALID_ENV(env); return ObjectUtil::GetObjectSize(env, object, size_ptr); } static jvmtiError GetObjectHashCode(jvmtiEnv* env, jobject object, jint* hash_code_ptr) { + ENSURE_VALID_ENV(env); return ObjectUtil::GetObjectHashCode(env, object, hash_code_ptr); } static jvmtiError GetObjectMonitorUsage(jvmtiEnv* env, jobject object ATTRIBUTE_UNUSED, jvmtiMonitorUsage* info_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_monitor_info); return ERR(NOT_IMPLEMENTED); } @@ -755,6 +841,7 @@ class JvmtiFunctions { char** name_ptr, char** signature_ptr, char** generic_ptr) { + ENSURE_VALID_ENV(env); return FieldUtil::GetFieldName(env, klass, field, name_ptr, signature_ptr, generic_ptr); } @@ -762,6 +849,7 @@ class JvmtiFunctions { jclass klass, jfieldID field, jclass* declaring_class_ptr) { + ENSURE_VALID_ENV(env); return FieldUtil::GetFieldDeclaringClass(env, klass, field, declaring_class_ptr); } @@ -769,6 +857,7 @@ class JvmtiFunctions { jclass klass, jfieldID field, jint* modifiers_ptr) { + ENSURE_VALID_ENV(env); return FieldUtil::GetFieldModifiers(env, klass, field, modifiers_ptr); } @@ -776,6 +865,7 @@ class JvmtiFunctions { jclass klass, jfieldID field, jboolean* is_synthetic_ptr) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_synthetic_attribute); return FieldUtil::IsFieldSynthetic(env, klass, field, is_synthetic_ptr); } @@ -785,30 +875,35 @@ class JvmtiFunctions { char** name_ptr, char** signature_ptr, char** generic_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetMethodName(env, method, name_ptr, signature_ptr, generic_ptr); } static jvmtiError GetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, jclass* declaring_class_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetMethodDeclaringClass(env, method, declaring_class_ptr); } static jvmtiError GetMethodModifiers(jvmtiEnv* env, jmethodID method, jint* modifiers_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetMethodModifiers(env, method, modifiers_ptr); } static jvmtiError GetMaxLocals(jvmtiEnv* env, jmethodID method, jint* max_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetMaxLocals(env, method, max_ptr); } static jvmtiError GetArgumentsSize(jvmtiEnv* env, jmethodID method, jint* size_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetArgumentsSize(env, method, size_ptr); } @@ -816,6 +911,7 @@ class JvmtiFunctions { jmethodID method, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_line_numbers); return MethodUtil::GetLineNumberTable(env, method, entry_count_ptr, table_ptr); } @@ -824,6 +920,7 @@ class JvmtiFunctions { jmethodID method, jlocation* start_location_ptr, jlocation* end_location_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::GetMethodLocation(env, method, start_location_ptr, end_location_ptr); } @@ -831,6 +928,7 @@ class JvmtiFunctions { jmethodID method ATTRIBUTE_UNUSED, jint* entry_count_ptr ATTRIBUTE_UNUSED, jvmtiLocalVariableEntry** table_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_access_local_variables); return ERR(NOT_IMPLEMENTED); } @@ -839,24 +937,29 @@ class JvmtiFunctions { jmethodID method ATTRIBUTE_UNUSED, jint* bytecode_count_ptr ATTRIBUTE_UNUSED, unsigned char** bytecodes_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_bytecodes); return ERR(NOT_IMPLEMENTED); } static jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::IsMethodNative(env, method, is_native_ptr); } static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_synthetic_attribute); return MethodUtil::IsMethodSynthetic(env, method, is_synthetic_ptr); } static jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr) { + ENSURE_VALID_ENV(env); return MethodUtil::IsMethodObsolete(env, method, is_obsolete_ptr); } static jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_set_native_method_prefix); return ERR(NOT_IMPLEMENTED); } @@ -864,43 +967,53 @@ class JvmtiFunctions { static jvmtiError SetNativeMethodPrefixes(jvmtiEnv* env, jint prefix_count ATTRIBUTE_UNUSED, char** prefixes ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_set_native_method_prefix); return ERR(NOT_IMPLEMENTED); } static jvmtiError CreateRawMonitor(jvmtiEnv* env, const char* name, jrawMonitorID* monitor_ptr) { + ENSURE_VALID_ENV(env); return MonitorUtil::CreateRawMonitor(env, name, monitor_ptr); } static jvmtiError DestroyRawMonitor(jvmtiEnv* env, jrawMonitorID monitor) { + ENSURE_VALID_ENV(env); return MonitorUtil::DestroyRawMonitor(env, monitor); } static jvmtiError RawMonitorEnter(jvmtiEnv* env, jrawMonitorID monitor) { + ENSURE_VALID_ENV(env); return MonitorUtil::RawMonitorEnter(env, monitor); } static jvmtiError RawMonitorExit(jvmtiEnv* env, jrawMonitorID monitor) { + ENSURE_VALID_ENV(env); return MonitorUtil::RawMonitorExit(env, monitor); } static jvmtiError RawMonitorWait(jvmtiEnv* env, jrawMonitorID monitor, jlong millis) { + ENSURE_VALID_ENV(env); return MonitorUtil::RawMonitorWait(env, monitor, millis); } static jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor) { + ENSURE_VALID_ENV(env); return MonitorUtil::RawMonitorNotify(env, monitor); } static jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor) { + ENSURE_VALID_ENV(env); return MonitorUtil::RawMonitorNotifyAll(env, monitor); } static jvmtiError SetJNIFunctionTable(jvmtiEnv* env, const jniNativeInterface* function_table) { + ENSURE_VALID_ENV(env); return JNIUtil::SetJNIFunctionTable(env, function_table); } static jvmtiError GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table) { + ENSURE_VALID_ENV(env); return JNIUtil::GetJNIFunctionTable(env, function_table); } @@ -955,14 +1068,16 @@ class JvmtiFunctions { return gEventHandler.SetEvent(art_env, art_thread, GetArtJvmtiEvent(art_env, event_type), mode); } - static jvmtiError GenerateEvents(jvmtiEnv* env ATTRIBUTE_UNUSED, + static jvmtiError GenerateEvents(jvmtiEnv* env, jvmtiEvent event_type ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); return OK; } - static jvmtiError GetExtensionFunctions(jvmtiEnv* env ATTRIBUTE_UNUSED, + static jvmtiError GetExtensionFunctions(jvmtiEnv* env, jint* extension_count_ptr, jvmtiExtensionFunctionInfo** extensions) { + ENSURE_VALID_ENV(env); // We do not have any extension functions. *extension_count_ptr = 0; *extensions = nullptr; @@ -970,9 +1085,10 @@ class JvmtiFunctions { return ERR(NONE); } - static jvmtiError GetExtensionEvents(jvmtiEnv* env ATTRIBUTE_UNUSED, + static jvmtiError GetExtensionEvents(jvmtiEnv* env, jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions) { + ENSURE_VALID_ENV(env); // We do not have any extension events. *extension_count_ptr = 0; *extensions = nullptr; @@ -980,9 +1096,10 @@ class JvmtiFunctions { return ERR(NONE); } - static jvmtiError SetExtensionEventCallback(jvmtiEnv* env ATTRIBUTE_UNUSED, + static jvmtiError SetExtensionEventCallback(jvmtiEnv* env, jint extension_event_index ATTRIBUTE_UNUSED, jvmtiExtensionEvent callback ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); // We do not have any extension events, so any call is illegal. return ERR(ILLEGAL_ARGUMENT); } @@ -1141,17 +1258,20 @@ class JvmtiFunctions { static jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_thread_cpu_time); return ERR(NOT_IMPLEMENTED); } @@ -1159,43 +1279,53 @@ class JvmtiFunctions { static jvmtiError GetThreadCpuTime(jvmtiEnv* env, jthread thread ATTRIBUTE_UNUSED, jlong* nanos_ptr ATTRIBUTE_UNUSED) { + ENSURE_VALID_ENV(env); ENSURE_HAS_CAP(env, can_get_thread_cpu_time); return ERR(NOT_IMPLEMENTED); } static jvmtiError GetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) { + ENSURE_VALID_ENV(env); return TimerUtil::GetTimerInfo(env, info_ptr); } static jvmtiError GetTime(jvmtiEnv* env, jlong* nanos_ptr) { + ENSURE_VALID_ENV(env); return TimerUtil::GetTime(env, nanos_ptr); } static jvmtiError GetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr) { + ENSURE_VALID_ENV(env); return TimerUtil::GetAvailableProcessors(env, processor_count_ptr); } static jvmtiError AddToBootstrapClassLoaderSearch(jvmtiEnv* env, const char* segment) { + ENSURE_VALID_ENV(env); return SearchUtil::AddToBootstrapClassLoaderSearch(env, segment); } static jvmtiError AddToSystemClassLoaderSearch(jvmtiEnv* env, const char* segment) { + ENSURE_VALID_ENV(env); return SearchUtil::AddToSystemClassLoaderSearch(env, segment); } static jvmtiError GetSystemProperties(jvmtiEnv* env, jint* count_ptr, char*** property_ptr) { + ENSURE_VALID_ENV(env); return PropertiesUtil::GetSystemProperties(env, count_ptr, property_ptr); } static jvmtiError GetSystemProperty(jvmtiEnv* env, const char* property, char** value_ptr) { + ENSURE_VALID_ENV(env); return PropertiesUtil::GetSystemProperty(env, property, value_ptr); } static jvmtiError SetSystemProperty(jvmtiEnv* env, const char* property, const char* value) { + ENSURE_VALID_ENV(env); return PropertiesUtil::SetSystemProperty(env, property, value); } static jvmtiError GetPhase(jvmtiEnv* env, jvmtiPhase* phase_ptr) { + ENSURE_VALID_ENV(env); return PhaseUtil::GetPhase(env, phase_ptr); } @@ -1303,9 +1433,10 @@ class JvmtiFunctions { } } - static jvmtiError SetVerboseFlag(jvmtiEnv* env ATTRIBUTE_UNUSED, + static jvmtiError SetVerboseFlag(jvmtiEnv* env, jvmtiVerboseFlag flag, jboolean value) { + ENSURE_VALID_ENV(env); if (flag == jvmtiVerboseFlag::JVMTI_VERBOSE_OTHER) { // OTHER is special, as it's 0, so can't do a bit check. bool val = (value == JNI_TRUE) ? true : false; @@ -1359,8 +1490,8 @@ class JvmtiFunctions { return ERR(NONE); } - static jvmtiError GetJLocationFormat(jvmtiEnv* env ATTRIBUTE_UNUSED, - jvmtiJlocationFormat* format_ptr) { + static jvmtiError GetJLocationFormat(jvmtiEnv* env, jvmtiJlocationFormat* format_ptr) { + ENSURE_VALID_ENV(env); // Report BCI as jlocation format. We report dex bytecode indices. if (format_ptr == nullptr) { return ERR(NULL_POINTER); diff --git a/test/901-hello-ti-agent/basics.cc b/test/901-hello-ti-agent/basics.cc index 91662770be..cbd768663b 100644 --- a/test/901-hello-ti-agent/basics.cc +++ b/test/901-hello-ti-agent/basics.cc @@ -16,6 +16,8 @@ #include "901-hello-ti-agent/basics.h" +#include <thread> + #include <jni.h> #include <stdio.h> #include <string.h> @@ -159,5 +161,19 @@ extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkLivePhase( return (current_phase == JVMTI_PHASE_LIVE) ? JNI_TRUE : JNI_FALSE; } +static void CallJvmtiFunction(jvmtiEnv* env, jclass klass, jvmtiError* err) { + jint n; + jmethodID* methods = nullptr; + *err = env->GetClassMethods(klass, &n, &methods); +} + +extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkUnattached( + JNIEnv* env ATTRIBUTE_UNUSED, jclass Main_klass) { + jvmtiError res = JVMTI_ERROR_NONE; + std::thread t1(CallJvmtiFunction, jvmti_env, Main_klass, &res); + t1.join(); + return res == JVMTI_ERROR_UNATTACHED_THREAD; +} + } // namespace Test901HelloTi } // namespace art diff --git a/test/901-hello-ti-agent/expected.txt b/test/901-hello-ti-agent/expected.txt index c4b24cba90..eb5b6a2f93 100644 --- a/test/901-hello-ti-agent/expected.txt +++ b/test/901-hello-ti-agent/expected.txt @@ -3,6 +3,7 @@ VMStart VMInit Hello, world! Agent in live phase. +Received expected error for unattached JVMTI calls 0 1 2 diff --git a/test/901-hello-ti-agent/src/Main.java b/test/901-hello-ti-agent/src/Main.java index 4d62ed3f5d..556e05b5d0 100644 --- a/test/901-hello-ti-agent/src/Main.java +++ b/test/901-hello-ti-agent/src/Main.java @@ -21,6 +21,9 @@ public class Main { if (checkLivePhase()) { System.out.println("Agent in live phase."); } + if (checkUnattached()) { + System.out.println("Received expected error for unattached JVMTI calls"); + } set(0); // OTHER set(1); // GC @@ -41,4 +44,5 @@ public class Main { private static native boolean checkLivePhase(); private static native void setVerboseFlag(int flag, boolean value); + private static native boolean checkUnattached(); } |