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
17import java.lang.reflect.InvocationTargetException;
18import java.lang.reflect.Method;
19
20public class Main {
21    static class ArrayMemEater {
22        static boolean sawOome;
23
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
42        static InstanceMemEater allocate() {
43            try {
44                return new InstanceMemEater();
45            } catch (OutOfMemoryError e) {
46                InstanceMemEater.sawOome = true;
47                return null;
48            }
49        }
50
51        static void confuseCompilerOptimization(InstanceMemEater instance) {
52          hook = instance;
53        }
54    }
55
56    static boolean triggerArrayOOM() {
57        ArrayMemEater.blowup(new char[128 * 1024][]);
58        return ArrayMemEater.sawOome;
59    }
60
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
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
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
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