/*
 * Copyright (C) 2009 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.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    static class ArrayMemEater {
        static boolean sawOome;

        static void blowup(char[][] holder) {
            try {
                for (int i = 0; i < holder.length; ++i) {
                    holder[i] = new char[1024 * 1024];
                }
            } catch (OutOfMemoryError oome) {
                ArrayMemEater.sawOome = true;
            }
        }
    }

    static class InstanceMemEater {
        static boolean sawOome;
        static InstanceMemEater hook;

        InstanceMemEater next;
        double d1, d2, d3, d4, d5, d6, d7, d8; // Bloat this object so we fill the heap faster.

        static InstanceMemEater allocate() {
            try {
                return new InstanceMemEater();
            } catch (OutOfMemoryError e) {
                InstanceMemEater.sawOome = true;
                return null;
            }
        }

        static void confuseCompilerOptimization(InstanceMemEater instance) {
          hook = instance;
        }
    }

    private static int exhaustJavaHeap(Object[] data, int index, int size) {
        Runtime.getRuntime().gc();
        while (index != data.length) {
            try {
                data[index] = new byte[size];
                ++index;
            } catch (OutOfMemoryError oome) {
                // Rapidly shrink the object size to fill any remaining space.
                // Use few different sizes, since detecting out-of-memory is slow.
                if (size >= 32) {
                    size /= 32;
                } else if (size > 1) {
                    size = 1;
                } else {
                    break;
                }
            }
        }
        return index;
    }

    public static Object eatAllMemory() {
        Object[] result = null;
        int size = 1000000;
        // Make sure that there is no reclaimable memory in the heap. Otherwise we may throw
        // OOME to prevent GC thrashing, even if later allocations may succeed.
        Runtime.getRuntime().gc();
        System.runFinalization();
        // NOTE: There is a GC invocation in exhaustJavaHeap. So we don't need one here.

        while (result == null && size != 0) {
            try {
                result = new Object[size];
            } catch (OutOfMemoryError oome) {
                size /= 2;
            }
        }
        if (result != null) {
            int index = 0;
            // Repeat to ensure there is no space left on the heap.
            index = exhaustJavaHeap(result, index, size);
            index = exhaustJavaHeap(result, index, /*size*/ 4);
            index = exhaustJavaHeap(result, index, /*size*/ 4);
        }
        return result;
    }

    static boolean triggerArrayOOM() {
        ArrayMemEater.blowup(new char[128 * 1024][]);
        return ArrayMemEater.sawOome;
    }

    static boolean triggerInstanceOOM() {
        InstanceMemEater memEater = InstanceMemEater.allocate();
        InstanceMemEater lastMemEater = memEater;
        do {
            lastMemEater.next = InstanceMemEater.allocate();
            lastMemEater = lastMemEater.next;
        } while (lastMemEater != null);
        memEater.confuseCompilerOptimization(memEater);
        InstanceMemEater.hook = null;
        return InstanceMemEater.sawOome;
    }

    public static void main(String[] args) {
        if (triggerReflectionOOM()) {
            System.out.println("Test reflection correctly threw");
        }
        if (triggerReflectionOOM2()) {
            System.out.println("Test reflection2 correctly threw");
        }

        if (triggerArrayOOM()) {
            System.out.println("NEW_ARRAY correctly threw OOME");
        }

        if (triggerInstanceOOM()) {
            System.out.println("NEW_INSTANCE correctly threw OOME");
        }
    }

    static Object[] holder;

    public static void blowup() throws Exception {
        int size = 2 * 1024 * 1024;
        for (int i = 0; i < holder.length; ) {
            try {
                holder[i] = new char[size];
                i++;
            } catch (OutOfMemoryError oome) {
                size = size / 16;
                if (size == 0) {
                     break;
                }
            }
        }
        holder[0] = new char[100000];
    }

    static boolean triggerReflectionOOM() {
        try {
            Class<?> c = Main.class;
            Method m = c.getMethod("blowup");
            holder = new Object[1000000];
            m.invoke(null);
            holder = null;
            System.out.println("Didn't throw from blowup");
        } catch (OutOfMemoryError e) {
            holder = null;
        } catch (InvocationTargetException e) {
            holder = null;
            if (!(e.getCause() instanceof OutOfMemoryError)) {
                System.out.println("InvocationTargetException cause not OOME " + e.getCause());
                return false;
            }
        } catch (Exception e) {
            holder = null;
            System.out.println("Unexpected exception " + e);
            return false;
        }
        return true;
    }

    static boolean triggerReflectionOOM2() {
        Object memory = eatAllMemory();
        boolean result = false;
        try {
            Main.class.getDeclaredMethods();
        } catch (OutOfMemoryError e) {
            result = true;
        }
        if (!result) {
            boolean memoryWasAllocated = (memory != null);
            memory = null;
            System.out.println("memoryWasAllocated = " + memoryWasAllocated);
        }
        return result;
    }
}
