1 /*
2  * Copyright (C) 2009 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 java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 
20 public class Main {
21     static class ArrayMemEater {
22         static boolean sawOome;
23 
blowup(char[][] holder)24         static void blowup(char[][] holder) {
25             try {
26                 for (int i = 0; i < holder.length; ++i) {
27                     holder[i] = new char[1024 * 1024];
28                 }
29             } catch (OutOfMemoryError oome) {
30                 ArrayMemEater.sawOome = true;
31             }
32         }
33     }
34 
35     static class InstanceMemEater {
36         static boolean sawOome;
37         static InstanceMemEater hook;
38 
39         InstanceMemEater next;
40         double d1, d2, d3, d4, d5, d6, d7, d8; // Bloat this object so we fill the heap faster.
41 
allocate()42         static InstanceMemEater allocate() {
43             try {
44                 return new InstanceMemEater();
45             } catch (OutOfMemoryError e) {
46                 InstanceMemEater.sawOome = true;
47                 return null;
48             }
49         }
50 
confuseCompilerOptimization(InstanceMemEater instance)51         static void confuseCompilerOptimization(InstanceMemEater instance) {
52           hook = instance;
53         }
54     }
55 
triggerArrayOOM()56     static boolean triggerArrayOOM() {
57         ArrayMemEater.blowup(new char[128 * 1024][]);
58         return ArrayMemEater.sawOome;
59     }
60 
triggerInstanceOOM()61     static boolean triggerInstanceOOM() {
62         InstanceMemEater memEater = InstanceMemEater.allocate();
63         InstanceMemEater lastMemEater = memEater;
64         do {
65             lastMemEater.next = InstanceMemEater.allocate();
66             lastMemEater = lastMemEater.next;
67         } while (lastMemEater != null);
68         memEater.confuseCompilerOptimization(memEater);
69         InstanceMemEater.hook = null;
70         return InstanceMemEater.sawOome;
71     }
72 
main(String[] args)73     public static void main(String[] args) {
74         if (triggerReflectionOOM()) {
75             System.out.println("Test reflection correctly threw");
76         }
77 
78         if (triggerArrayOOM()) {
79             System.out.println("NEW_ARRAY correctly threw OOME");
80         }
81 
82         if (triggerInstanceOOM()) {
83             System.out.println("NEW_INSTANCE correctly threw OOME");
84         }
85     }
86 
87     static Object[] holder;
88 
blowup()89     public static void blowup() throws Exception {
90         int size = 32 * 1024 * 1024;
91         for (int i = 0; i < holder.length; ) {
92             try {
93                 holder[i] = new char[size];
94                 i++;
95             } catch (OutOfMemoryError oome) {
96                 size = size / 2;
97                 if (size == 0) {
98                      break;
99                 }
100             }
101         }
102         holder[0] = new char[100000];
103     }
104 
triggerReflectionOOM()105     static boolean triggerReflectionOOM() {
106         try {
107             Class<?> c = Main.class;
108             Method m = c.getMethod("blowup", (Class[]) null);
109             holder = new Object[1000000];
110             m.invoke(null);
111             holder = null;
112             System.out.println("Didn't throw from blowup");
113         } catch (OutOfMemoryError e) {
114             holder = null;
115         } catch (InvocationTargetException e) {
116             holder = null;
117             if (!(e.getCause() instanceof OutOfMemoryError)) {
118                 System.out.println("InvocationTargetException cause not OOME " + e.getCause());
119                 return false;
120             }
121         } catch (Exception e) {
122             holder = null;
123             System.out.println("Unexpected exception " + e);
124             return false;
125         }
126         return true;
127     }
128 }
129