1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import AAA.Derived;
18 
19 public class Main {
main(String[] args)20     public static void main(String[] args) {
21         try {
22             // Allocate memory for the "AAA.Derived" class name before eating memory.
23             String aaaDerivedName = "AAA.Derived";
24             System.out.println("Eating all memory.");
25             // Resolve VMClassLoader before eating all the memory since we can not fail
26             // initialization of boot classpath classes.
27             Class.forName("java.lang.VMClassLoader");
28             Object memory = eatAllMemory();
29 
30             // This test assumes that Derived is not yet resolved. In some configurations
31             // (notably interp-ac), Derived is already resolved by verifying Main at run
32             // time. Therefore we cannot assume that we get a certain `value` and need to
33             // simply check for consistency, i.e. `value == another_value`.
34             int value = 0;
35             try {
36                 // If the ArtMethod* is erroneously left in the DexCache, this
37                 // shall succeed despite the class Derived being unresolved so
38                 // far. Otherwise, we shall throw OOME trying to resolve it.
39                 value = Derived.foo();
40             } catch (OutOfMemoryError e) {
41                 value = -1;
42             }
43             int another_value = 0;
44             try {
45                 // For comparison, try to resolve the class Derived directly.
46                 Class.forName(aaaDerivedName, false, Main.class.getClassLoader());
47                 another_value = 42;
48             } catch (OutOfMemoryError e) {
49                 another_value = -1;
50             }
51             boolean memoryWasAllocated = (memory != null);
52             memory = null;
53             System.out.println("memoryWasAllocated = " + memoryWasAllocated);
54             System.out.println("match: " + (value == another_value));
55             if (value != another_value || (value != -1 && value != 42)) {
56                 // Mismatch or unexpected value, print additional debugging information.
57                 System.out.println("value: " + value);
58                 System.out.println("another_value: " + another_value);
59             }
60         } catch (Throwable t) {
61             t.printStackTrace(System.out);
62         }
63     }
64 
eatAllMemory()65     public static Object eatAllMemory() {
66       Object[] result = null;
67       int size = 1000000;
68       while (result == null && size != 0) {
69           try {
70               result = new Object[size];
71           } catch (OutOfMemoryError oome) {
72               size /= 2;
73           }
74       }
75       if (result != null) {
76           int index = 0;
77           while (index != result.length && size != 0) {
78               try {
79                   result[index] = new byte[size];
80                   ++index;
81               } catch (OutOfMemoryError oome) {
82                   size /= 2;
83               }
84           }
85       }
86       return result;
87   }
88 }
89