diff options
Diffstat (limited to 'test/174-escaping-instance-of-bad-class/src/Main.java')
-rw-r--r-- | test/174-escaping-instance-of-bad-class/src/Main.java | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/test/174-escaping-instance-of-bad-class/src/Main.java b/test/174-escaping-instance-of-bad-class/src/Main.java new file mode 100644 index 0000000000..4346152f6c --- /dev/null +++ b/test/174-escaping-instance-of-bad-class/src/Main.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2018 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. + */ + +public class Main { + public static void main(String args[]) { + simpleTest(); + hierarchyTest(); + } + + public static void simpleTest() { + // Partial initialization of Bad; ignoring the error. + Error badClinit = null; + try { + new Bad(11); + } catch (Error e) { + badClinit = e; + } + // Call foo() on the escaped instance of Bad. + try { + bad.foo(); + } catch (NoClassDefFoundError ncdfe) { + // On RI, the NCDFE has no cause. On ART, the badClinit is the cause. + if (ncdfe.getCause() == badClinit || ncdfe.getCause() == null) { + System.out.println("Caught NoClassDefFoundError."); + } else { + ncdfe.printStackTrace(); + } + } + } + + public static void hierarchyTest() { + // Partial initialization of BadSuper; ignoring the error. Fully initializes BadSub. + Error badClinit = null; + try { + new BadSuper(0); + } catch (Error e) { + badClinit = e; + } + // Call BadSuper.foo() on the escaped instance of BadSuper. + try { + badSuper.foo(); + } catch (NoClassDefFoundError ncdfe) { + // On RI, the NCDFE has no cause. On ART, the badClinit is the cause. + if (ncdfe.getCause() == badClinit || ncdfe.getCause() == null) { + System.out.println("Caught NoClassDefFoundError."); + } else { + ncdfe.printStackTrace(); + } + } + + // Call BadSub.bar() on the escaped instance of BadSub. + try { + badSub.bar(); + } catch (NoClassDefFoundError ncdfe) { + // On RI, the NCDFE has no cause. On ART, the badClinit is the cause. + if (ncdfe.getCause() == badClinit || ncdfe.getCause() == null) { + System.out.println("Caught NoClassDefFoundError."); + } else { + ncdfe.printStackTrace(); + } + } + + // Test that we can even create instances of BadSub with erroneous superclass BadSuper. + try { + new BadSub(-1, -2).bar(); + } catch (NoClassDefFoundError ncdfe) { + // On RI, the NCDFE has no cause. On ART, the badClinit is the cause. + if (ncdfe.getCause() == badClinit || ncdfe.getCause() == null) { + System.out.println("Caught NoClassDefFoundError."); + } else { + ncdfe.printStackTrace(); + } + } + + // Test that we cannot create instances of BadSuper from BadSub. + try { + badSub.allocSuper(11111); // Should throw. + System.out.println("Allocated BadSuper!"); + } catch (NoClassDefFoundError ncdfe) { + // On RI, the NCDFE has no cause. On ART, the badClinit is the cause. + if (ncdfe.getCause() == badClinit || ncdfe.getCause() == null) { + System.out.println("Caught NoClassDefFoundError."); + } else { + ncdfe.printStackTrace(); + } + } + } + + public static Bad bad; + + public static BadSuper badSuper; + public static BadSub badSub; +} + +class Bad { + static { + // Create an instance of Bad and let it escape in Main.bad. + Main.bad = new Bad(33); + staticValue = 42; + if (true) { throw new Error("Bad <clinit>"); } + } + public void foo() { + System.out.println("Bad.foo()"); + System.out.println("Bad.instanceValue = " + instanceValue); + System.out.println("Bad.staticValue = " + staticValue); + } + public Bad(int iv) { instanceValue = iv; } + public int instanceValue; + public static int staticValue; +} + +class BadSuper { + static { + Main.badSuper = new BadSuper(1); + Main.badSub = new BadSub(11, 111); // Fully initializes BadSub. + BadSuper.superStaticValue = 42; + BadSub.subStaticValue = 4242; + if (true) { throw new Error("Bad <clinit>"); } + } + public void foo() { + System.out.println("BadSuper.foo()"); + System.out.println("BadSuper.superInstanceValue = " + superInstanceValue); + System.out.println("BadSuper.superStaticValue = " + superStaticValue); + } + public BadSuper(int superiv) { superInstanceValue = superiv; } + public int superInstanceValue; + public static int superStaticValue; +} + +// Note: If we tried to initialize BadSub before BadSuper, it would end up erroneous +// because the superclass fails initialization. However, since we start initializing the +// BadSuper first, BadSub is initialized successfully while BadSuper is "initializing" +// and remains initialized after the BadSuper's class initializer throws. +class BadSub extends BadSuper { + public void bar() { + System.out.println("BadSub.bar()"); + System.out.println("BadSub.subInstanceValue = " + subInstanceValue); + System.out.println("BadSub.subStaticValue = " + subStaticValue); + System.out.println("BadSuper.superInstanceValue = " + superInstanceValue); + System.out.println("BadSuper.superStaticValue = " + superStaticValue); + } + public BadSuper allocSuper(int superiv) { + System.out.println("BadSub.allocSuper(.)"); + return new BadSuper(superiv); + } + public BadSub(int subiv, int superiv) { + super(superiv); + subInstanceValue = subiv; + } + public int subInstanceValue; + public static int subStaticValue; +} |