Ensure shutdown thread has a java peer.

Using JVMTI it is possible to be running user-supplied code both on
the shutdown thread and on other threads while the shutdown thread is
running. Specifically some real-world JVMTI agents rely on being able
to suspend the shutdown thread while they do cleanup work. In order to
support this we will make sure that the shutdown thread is given its
own java peer so it can be suspended by other threads.

Bug: 66904725
Bug: 62821960

Test: ./test.py --host -j50

Change-Id: I1c89537c47fd3dd41aa4c0e7f7a6940d1c5ba913
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 37ba9e4..42f724a 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -290,7 +290,12 @@
   Thread* self = Thread::Current();
   const bool attach_shutdown_thread = self == nullptr;
   if (attach_shutdown_thread) {
-    CHECK(AttachCurrentThread("Shutdown thread", false, nullptr, false));
+    // We can only create a peer if the runtime is actually started. This is only not true during
+    // some tests.
+    CHECK(AttachCurrentThread("Shutdown thread",
+                              false,
+                              GetSystemThreadGroup(),
+                              /* Create peer */IsStarted()));
     self = Thread::Current();
   } else {
     LOG(WARNING) << "Current thread not detached in Runtime shutdown";
diff --git a/test/901-hello-ti-agent/basics.cc b/test/901-hello-ti-agent/basics.cc
index 472f2b7..43a1d83 100644
--- a/test/901-hello-ti-agent/basics.cc
+++ b/test/901-hello-ti-agent/basics.cc
@@ -56,9 +56,13 @@
   fsync(1);
 }
 
-static void JNICALL VMDeatchCallback(jvmtiEnv *jenv, JNIEnv* jni_env ATTRIBUTE_UNUSED) {
+static void JNICALL VMDeathCallback(jvmtiEnv *jenv, JNIEnv* jni_env) {
   printf("VMDeath (phase %d)\n", getPhase(jenv));
   fsync(1);
+  jthread cur_thr;
+  CHECK_EQ(jenv->GetCurrentThread(&cur_thr), JVMTI_ERROR_NONE);
+  CHECK(cur_thr != nullptr);
+  jni_env->DeleteLocalRef(cur_thr);
 }
 
 
@@ -67,7 +71,7 @@
   memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
   callbacks.VMStart = VMStartCallback;
   callbacks.VMInit = VMInitCallback;
-  callbacks.VMDeath = VMDeatchCallback;
+  callbacks.VMDeath = VMDeathCallback;
   jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks));
   if (ret != JVMTI_ERROR_NONE) {
     printf("Failed to install callbacks");
diff --git a/test/980-redefine-object/expected.txt b/test/980-redefine-object/expected.txt
index 4c294bc..0a80882 100644
--- a/test/980-redefine-object/expected.txt
+++ b/test/980-redefine-object/expected.txt
@@ -30,3 +30,7 @@
 Object allocated of type 'java.lang.Exception'
 	Exception caught.
 	Finishing test!
+Object allocated of type 'java.lang.Thread'
+Object allocated of type 'java.lang.Object'
+Object allocated of type 'java.lang.Object'
+Object allocated of type 'java.security.AccessControlContext'