Fix UnstartedRunime leaking local reference.

And assert that class initialization in CompilerDriver
does not leave any local references alive.

Test: m test-art-host-gtest
Change-Id: Icd6a141da340d21d0103308a9e056009eb86f485
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index c94c57f..def5af9 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -2119,7 +2119,7 @@
 
     if (klass != nullptr) {
       if (!SkipClass(manager_->GetClassLoader(), dex_file, klass.Get())) {
-        TryInitializeClass(klass, class_loader);
+        TryInitializeClass(soa.Self(), klass, class_loader);
       }
       manager_->GetCompiler()->stats_->AddClassStatus(klass->GetStatus());
     }
@@ -2128,14 +2128,15 @@
   }
 
   // A helper function for initializing klass.
-  void TryInitializeClass(Handle<mirror::Class> klass, Handle<mirror::ClassLoader>& class_loader)
+  void TryInitializeClass(Thread* self,
+                          Handle<mirror::Class> klass,
+                          Handle<mirror::ClassLoader>& class_loader)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     const DexFile& dex_file = klass->GetDexFile();
     const dex::ClassDef* class_def = klass->GetClassDef();
     const dex::TypeId& class_type_id = dex_file.GetTypeId(class_def->class_idx_);
     const char* descriptor = dex_file.StringDataByIdx(class_type_id.descriptor_idx_);
-    ScopedObjectAccessUnchecked soa(Thread::Current());
-    StackHandleScope<3> hs(soa.Self());
+    StackHandleScope<3> hs(self);
     ClassLinker* const class_linker = manager_->GetClassLinker();
     Runtime* const runtime = Runtime::Current();
     const CompilerOptions& compiler_options = manager_->GetCompiler()->GetCompilerOptions();
@@ -2160,7 +2161,7 @@
     if (klass->IsVerified()) {
       // Attempt to initialize the class but bail if we either need to initialize the super-class
       // or static fields.
-      class_linker->EnsureInitialized(soa.Self(), klass, false, false);
+      class_linker->EnsureInitialized(self, klass, false, false);
       old_status = klass->GetStatus();
       if (!klass->IsInitialized()) {
         // We don't want non-trivial class initialization occurring on multiple threads due to
@@ -2172,18 +2173,18 @@
         // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
         // than use a special Object for the purpose we use the Class of java.lang.Class.
         Handle<mirror::Class> h_klass(hs.NewHandle(klass->GetClass()));
-        ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
+        ObjectLock<mirror::Class> lock(self, h_klass);
         // Attempt to initialize allowing initialization of parent classes but still not static
         // fields.
         // Initialize dependencies first only for app or boot image extension,
         // to make TryInitializeClass() recursive.
         bool try_initialize_with_superclasses =
-            is_boot_image ? true : InitializeDependencies(klass, class_loader, soa.Self());
+            is_boot_image ? true : InitializeDependencies(klass, class_loader, self);
         if (try_initialize_with_superclasses) {
-          class_linker->EnsureInitialized(soa.Self(), klass, false, true);
+          class_linker->EnsureInitialized(self, klass, false, true);
           // It's OK to clear the exception here since the compiler is supposed to be fault
           // tolerant and will silently not initialize classes that have exceptions.
-          soa.Self()->ClearException();
+          self->ClearException();
         }
         // Otherwise it's in app image or boot image extension but superclasses
         // cannot be initialized, no need to proceed.
@@ -2214,10 +2215,10 @@
             // <clinit> at compile time.
             can_init_static_fields =
                 ClassLinker::kAppImageMayContainStrings &&
-                !soa.Self()->IsExceptionPending() &&
+                !self->IsExceptionPending() &&
                 !compiler_options.GetDebuggable() &&
                 (compiler_options.InitializeAppImageClasses() ||
-                 NoClinitInDependency(klass, soa.Self(), &class_loader));
+                 NoClinitInDependency(klass, self, &class_loader));
             // TODO The checking for clinit can be removed since it's already
             // checked when init superclass. Currently keep it because it contains
             // processing of intern strings. Will be removed later when intern strings
@@ -2236,17 +2237,17 @@
             // TransactionAbortError is not initialized ant not in boot image, needed only by
             // compiler and will be pruned by ImageWriter.
             Handle<mirror::Class> exception_class =
-                hs.NewHandle(class_linker->FindClass(soa.Self(),
+                hs.NewHandle(class_linker->FindClass(self,
                                                      Transaction::kAbortExceptionSignature,
                                                      class_loader));
             bool exception_initialized =
-                class_linker->EnsureInitialized(soa.Self(), exception_class, true, true);
+                class_linker->EnsureInitialized(self, exception_class, true, true);
             DCHECK(exception_initialized);
 
             // Run the class initializer in transaction mode.
             runtime->EnterTransactionMode(is_app_image, klass.Get());
 
-            bool success = class_linker->EnsureInitialized(soa.Self(), klass, true, true);
+            bool success = class_linker->EnsureInitialized(self, klass, true, true);
             // TODO we detach transaction from runtime to indicate we quit the transactional
             // mode which prevents the GC from visiting objects modified during the transaction.
             // Ensure GC is not run so don't access freed objects when aborting transaction.
@@ -2265,8 +2266,8 @@
                   old_status = klass->GetStatus();
                 }
               } else {
-                CHECK(soa.Self()->IsExceptionPending());
-                mirror::Throwable* exception = soa.Self()->GetException();
+                CHECK(self->IsExceptionPending());
+                mirror::Throwable* exception = self->GetException();
                 VLOG(compiler) << "Initialization of " << descriptor << " aborted because of "
                                << exception->Dump();
                 std::ostream* file_log = manager_->GetCompiler()->
@@ -2275,7 +2276,7 @@
                   *file_log << descriptor << "\n";
                   *file_log << exception->Dump() << "\n";
                 }
-                soa.Self()->ClearException();
+                self->ClearException();
                 runtime->RollbackAllTransactions();
                 CHECK_EQ(old_status, klass->GetStatus()) << "Previous class status not restored";
               }
@@ -2298,16 +2299,16 @@
         // Clear exception in case EnsureInitialized has caused one in the code above.
         // It's OK to clear the exception here since the compiler is supposed to be fault
         // tolerant and will silently not initialize classes that have exceptions.
-        soa.Self()->ClearException();
+        self->ClearException();
 
         // If the class still isn't initialized, at least try some checks that initialization
         // would do so they can be skipped at runtime.
         if (!klass->IsInitialized() && class_linker->ValidateSuperClassDescriptors(klass)) {
           old_status = ClassStatus::kSuperclassValidated;
         } else {
-          soa.Self()->ClearException();
+          self->ClearException();
         }
-        soa.Self()->AssertNoPendingException();
+        self->AssertNoPendingException();
       }
     }
     if (old_status == ClassStatus::kInitialized) {
@@ -2319,6 +2320,11 @@
     // Back up the status before doing initialization for static encoded fields,
     // because the static encoded branch wants to keep the status to uninitialized.
     manager_->GetCompiler()->RecordClassStatus(ref, old_status);
+
+    if (kIsDebugBuild) {
+      // Make sure the class initialization did not leave any local references.
+      self->GetJniEnv()->AssertLocalsEmpty();
+    }
   }
 
  private:
@@ -2438,7 +2444,7 @@
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> super_class = hs.NewHandle(klass->GetSuperClass());
       if (!super_class->IsInitialized()) {
-        this->TryInitializeClass(super_class, class_loader);
+        this->TryInitializeClass(self, super_class, class_loader);
         if (!super_class->IsInitialized()) {
           return false;
         }
@@ -2451,7 +2457,7 @@
         StackHandleScope<1> hs(self);
         Handle<mirror::Class> iface = hs.NewHandle(klass->GetIfTable()->GetInterface(i));
         if (iface->HasDefaultMethods() && !iface->IsInitialized()) {
-          TryInitializeClass(iface, class_loader);
+          TryInitializeClass(self, iface, class_loader);
           if (!iface->IsInitialized()) {
             return false;
           }
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index ec5f757..2c040ab 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1865,7 +1865,8 @@
     Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
     uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   ScopedObjectAccessUnchecked soa(self);
-  result->SetL(soa.Decode<mirror::Object>(self->CreateInternalStackTrace(soa)));
+  ScopedLocalRef<jobject> stack_trace(self->GetJniEnv(), self->CreateInternalStackTrace(soa));
+  result->SetL(soa.Decode<mirror::Object>(stack_trace.get()));
 }
 
 void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(