/* * Copyright (C) 2008 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.util.Arrays; import java.util.LinkedList; /** * Exercise the construction and throwing of OutOfMemoryError. */ public class Main { public static void main(String args[]) { System.out.println("tests beginning"); testHugeArray(); testOomeLarge(); testOomeSmall(); testOomeToCharArray(); System.out.println("tests succeeded"); } private static void testHugeArray() { try { final int COUNT = 32768*32768 + 4; int[] tooBig = new int[COUNT]; Arrays.fill(tooBig, 0xdd); } catch (OutOfMemoryError oom) { System.out.println("Got expected huge-array OOM"); } } private static void testOomeLarge() { System.out.println("testOomeLarge beginning"); Boolean sawEx = false; byte[] a; try { // Just shy of the typical max heap size so that it will actually // try to allocate it instead of short-circuiting. a = new byte[(int) Runtime.getRuntime().maxMemory() - 32]; } catch (OutOfMemoryError oom) { //Log.i(TAG, "HeapTest/OomeLarge caught " + oom); sawEx = true; } if (!sawEx) { throw new RuntimeException("Test failed: " + "OutOfMemoryError not thrown"); } System.out.println("testOomeLarge succeeded"); } /* Do this in another method so that the GC has a chance of freeing the * list afterwards. Even if we null out list when we're done, the conservative * GC may see a stale pointer to it in a register. */ private static boolean testOomeSmallInternal() { final int LINK_SIZE = 6 * 4; // estimated size of a LinkedList's node LinkedList<Object> list = new LinkedList<Object>(); /* Allocate progressively smaller objects to fill up the entire heap. */ int objSize = 1 * 1024 * 1024; while (objSize >= LINK_SIZE) { boolean sawEx = false; try { for (int i = 0; i < Runtime.getRuntime().maxMemory() / objSize; i++) { list.add((Object)new byte[objSize]); } } catch (OutOfMemoryError oom) { sawEx = true; } if (!sawEx) { return false; } objSize = (objSize * 4) / 5; } return true; } private static void testOomeSmall() { System.out.println("testOomeSmall beginning"); if (!testOomeSmallInternal()) { /* Can't reliably throw this from inside the internal function, because * we may not be able to allocate the RuntimeException. */ throw new RuntimeException("Test failed: " + "OutOfMemoryError not thrown while filling heap"); } System.out.println("testOomeSmall succeeded"); } private static void testOomeToCharArray() { Object[] o = new Object[2000000]; String test = "test"; int i = 0; try { for (; i < o.length; ++i) o[i] = new char[1000000]; } catch (OutOfMemoryError oom) {} try { for (; i < o.length; ++i) { o[i] = test.toCharArray(); } } catch (OutOfMemoryError oom) { o = null; System.out.println("Got expected toCharArray OOM"); } } }