OSDN Git Service

ExceptionInInitializerError should wrap only non Error exceptions.
authorElliott Hughes <enh@google.com>
Mon, 10 Dec 2012 22:51:07 +0000 (14:51 -0800)
committerElliott Hughes <enh@google.com>
Mon, 10 Dec 2012 22:51:07 +0000 (14:51 -0800)
Backport from dalvik-dev, due to customer demand.

Bug: http://code.google.com/p/android/issues/detail?id=41196
Change-Id: I53ef57e54983f2173546463ac78e265ff5dd3284

tests/084-class-init/expected.txt
tests/084-class-init/src/Exploder.java [new file with mode: 0644]
tests/084-class-init/src/Main.java
vm/Exception.cpp

index 6e74fbb..68a2b38 100644 (file)
@@ -1,6 +1,7 @@
 Got expected EIIE for FIELD0
 Got expected NCDFE for FIELD0
 Got expected NCDFE for FIELD1
+Got expected 'hello!' from Exploder
 SlowInit static block pre-sleep
 SlowInit static block post-sleep
 MethodThread message
diff --git a/tests/084-class-init/src/Exploder.java b/tests/084-class-init/src/Exploder.java
new file mode 100644 (file)
index 0000000..911e5fe
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Throws an Error rather than an exception from its class initializer.
+ */
+public class Exploder {
+    public static final Object FIELD = new AssertThrower();
+    static class AssertThrower {
+        AssertThrower() {
+            throw new AssertionError("hello!");
+        }
+    }
+}
index de28ed9..29681ce 100644 (file)
@@ -48,6 +48,13 @@ public class Main {
         } catch (NoClassDefFoundError ncdfe) {
             System.out.println("Got expected NCDFE for FIELD1");
         }
+
+        try {
+            System.out.println(Exploder.FIELD);
+            System.err.println("Load of FIELD succeeded unexpectedly");
+        } catch (AssertionError expected) {
+            System.out.println("Got expected '" + expected.getMessage() + "' from Exploder");
+        }
     }
 
     static void checkTiming() {
index de6d9a9..ca76140 100644 (file)
@@ -1271,13 +1271,10 @@ void dvmThrowChainedClassNotFoundException(const char* name, Object* cause) {
 void dvmThrowExceptionInInitializerError()
 {
     /*
-     * TODO: Do we want to wrap it if the original is an Error rather than
-     * an Exception?
-     *
      * TODO: Should this just use dvmWrapException()?
      */
 
-    if (gDvm.exExceptionInInitializerError == NULL) {
+    if (gDvm.exExceptionInInitializerError == NULL || gDvm.exError == NULL) {
         /*
          * ExceptionInInitializerError isn't itself initialized. This
          * can happen very early during VM startup if there is a
@@ -1294,6 +1291,11 @@ void dvmThrowExceptionInInitializerError()
     Thread* self = dvmThreadSelf();
     Object* exception = dvmGetException(self);
 
+    // We only wrap non-Error exceptions; an Error can just be used as-is.
+    if (dvmInstanceof(exception->clazz, gDvm.exError)) {
+        return;
+    }
+
     dvmAddTrackedAlloc(exception, self);
     dvmClearException(self);