Check for unattached threads in JVMTI functions

Calling the JVMTI functions with an unattached thread is required to
return JVMTI_ERROR_UNATTACHED_THREAD.

Test: ./test.py --host -j40
Bug: 36576873
Change-Id: I312b4e0a5e5fb66961f6efcc36d9480626c3461f
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 5401e5c..735b4c0 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -79,20 +79,26 @@
 
 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 @@
   }
 
   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 @@
                                       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 @@
                                      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 @@
   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 @@
                                         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 @@
       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 @@
   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 @@
                                    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 @@
                                            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 @@
                                   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 @@
                                       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 @@
                                              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 @@
   }
 
   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 @@
                                      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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
                                      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 @@
                                        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 @@
   }
 
   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 @@
                                        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 @@
   }
 
   static jvmtiError ForceGarbageCollection(jvmtiEnv* env) {
+    ENSURE_VALID_ENV(env);
     return HeapUtil::ForceGarbageCollection(env);
   }
 
@@ -430,6 +474,7 @@
       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 @@
       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 @@
                                     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 @@
       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 @@
                                    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 @@
                                      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 @@
                                 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 @@
                                  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 @@
                                   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 @@
                                    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 @@
                                    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 @@
                                 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 @@
                                  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 @@
                                   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 @@
                                    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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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 @@
                                           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 @@
                                       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 @@
                                     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 @@
                                    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 @@
                                              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 @@
                                            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 @@
                                     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 @@
   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 @@
   }
 
   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 @@
                                  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 @@
                                            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 @@
                                       jclass klass,
                                       jfieldID field,
                                       jint* modifiers_ptr) {
+    ENSURE_VALID_ENV(env);
     return FieldUtil::GetFieldModifiers(env, klass, field, modifiers_ptr);
   }
 
@@ -776,6 +865,7 @@
                                      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 @@
                                   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 @@
                                        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 @@
                                       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 @@
                                           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 @@
                                  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 @@
   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 @@
     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 @@
     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 @@
     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 @@
 
   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 @@
   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 @@
     }
   }
 
-  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 @@
     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 9166277..cbd7686 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 @@
   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 c4b24cb..eb5b6a2 100644
--- a/test/901-hello-ti-agent/expected.txt
+++ b/test/901-hello-ti-agent/expected.txt
@@ -3,6 +3,7 @@
 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 4d62ed3..556e05b 100644
--- a/test/901-hello-ti-agent/src/Main.java
+++ b/test/901-hello-ti-agent/src/Main.java
@@ -21,6 +21,9 @@
     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 @@
 
   private static native boolean checkLivePhase();
   private static native void setVerboseFlag(int flag, boolean value);
+  private static native boolean checkUnattached();
 }