Don't wrap exception when transaction is aborted

In unstarted runtime,to abort a transaction we use
a fake exception named TransactionAbortError which
should never be caught by the bytecode, therefore
it makes no sense to wrap it, else invoking the
constructor for the wrap exception could violate
the write value constraint in transaction.

It's a difficult to write a regression test which
need compile a dex file with a class that uses
special reflection in <clinit> as a boot image
extension.

Test: m test-art-host-gtest
Bug: 176505353

Signed-off-by: liulvping <liulvping@xiaomi.com>
Change-Id: I0f0e0317d140b48e38169b4eb6a68d8749708e41
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3b668a2..771e012 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -494,18 +494,26 @@
 
   // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
   if (soa.Self()->IsExceptionPending()) {
-    // If we get another exception when we are trying to wrap, then just use that instead.
-    ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
-    soa.Self()->ClearException();
-    jobject exception_instance =
-        soa.Env()->NewObject(WellKnownClasses::java_lang_reflect_InvocationTargetException,
-                             WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
-                             th.get());
-    if (exception_instance == nullptr) {
-      soa.Self()->AssertPendingException();
-      return false;
+    // To abort a transaction we use a fake exception that should never be caught by the bytecode
+    // and therefore it makes no sense to wrap it.
+    if (Runtime::Current()->IsTransactionAborted()) {
+      DCHECK(soa.Self()->GetException()->GetClass()->DescriptorEquals(
+                  "Ldalvik/system/TransactionAbortError;"))
+          << soa.Self()->GetException()->GetClass()->PrettyDescriptor();
+    } else {
+      // If we get another exception when we are trying to wrap, then just use that instead.
+      ScopedLocalRef<jthrowable> th(soa.Env(), soa.Env()->ExceptionOccurred());
+      soa.Self()->ClearException();
+      jobject exception_instance =
+          soa.Env()->NewObject(WellKnownClasses::java_lang_reflect_InvocationTargetException,
+                               WellKnownClasses::java_lang_reflect_InvocationTargetException_init,
+                               th.get());
+      if (exception_instance == nullptr) {
+        soa.Self()->AssertPendingException();
+        return false;
+      }
+      soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
     }
-    soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
     return false;
   }