/* * Copyright (C) 2018 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 dalvik.system.VMRuntime; import java.lang.ref.Reference; // For reachabilityFence. import java.util.ArrayList; public class Main { private static final boolean SHOULD_PRINT = false; // True causes failure. public static void main(String[] args) throws Exception { VMRuntime runtime = VMRuntime.getRuntime(); try { int N = 1024 * 1024; int S = 512; for (int n = 0; n < N; ++n) { // Allocate unreachable objects. $noinline$Alloc(runtime); // Allocate an object with a substantial size to increase memory // pressure and eventually trigger non-explicit garbage collection // (explicit garbage collections triggered by java.lang.Runtime.gc() // are always full GCs). Upon garbage collection, the objects // allocated in $noinline$Alloc used to trigger a crash. Object[] moving_array = new Object[S]; } } catch (OutOfMemoryError e) { System.out.println("Unexpected OOME"); } Runtime.getRuntime().gc(); int numAllocs = 0; ArrayList chunks = new ArrayList<>(); try { final int MAX_PLAUSIBLE_ALLOCS = 1024 * 1024; for (numAllocs = 0; numAllocs < MAX_PLAUSIBLE_ALLOCS; ++numAllocs) { chunks.add(runtime.newNonMovableArray(Object.class, 252)); // About 1KB } // If we get here, we've allocated about 1GB of nonmovable memory, which // should be impossible. } catch (OutOfMemoryError e) { chunks.remove(0); // Give us a little space back. if (((Object[]) (chunks.get(42)))[17] != null) { System.out.println("Bad entry in chunks array"); } else { chunks.clear(); // Recover remaining space. if (SHOULD_PRINT) { System.out.println("Successfully allocated " + numAllocs + " non-movable KBs"); } System.out.println("passed"); } Reference.reachabilityFence(chunks); return; } Reference.reachabilityFence(chunks); System.out.println("Failed to exhaust non-movable space"); } // When using the Concurrent Copying (CC) collector (default collector), // this method allocates an object in the non-moving space and an object // in the region space, make the former reference the later, and returns // nothing (so that none of these objects are reachable upon return). static void $noinline$Alloc(VMRuntime runtime) { Object[] non_moving_array = (Object[]) runtime.newNonMovableArray(Object.class, 1); // Small object, unlikely to trigger garbage collection. non_moving_array[0] = new Object(); } }