1 /* 2 * Copyright (C) 2018 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 dalvik.system.VMRuntime; 18 import java.lang.ref.Reference; // For reachabilityFence. 19 import java.util.ArrayList; 20 21 public class Main { 22 private static final boolean SHOULD_PRINT = false; // True causes failure. 23 main(String[] args)24 public static void main(String[] args) throws Exception { 25 VMRuntime runtime = VMRuntime.getRuntime(); 26 27 try { 28 int N = 1024 * 1024; 29 int S = 512; 30 for (int n = 0; n < N; ++n) { 31 // Allocate unreachable objects. 32 $noinline$Alloc(runtime); 33 // Allocate an object with a substantial size to increase memory 34 // pressure and eventually trigger non-explicit garbage collection 35 // (explicit garbage collections triggered by java.lang.Runtime.gc() 36 // are always full GCs). Upon garbage collection, the objects 37 // allocated in $noinline$Alloc used to trigger a crash. 38 Object[] moving_array = new Object[S]; 39 } 40 } catch (OutOfMemoryError e) { 41 System.out.println("Unexpected OOME"); 42 } 43 Runtime.getRuntime().gc(); 44 int numAllocs = 0; 45 ArrayList<Object> chunks = new ArrayList<>(); 46 try { 47 final int MAX_PLAUSIBLE_ALLOCS = 1024 * 1024; 48 for (numAllocs = 0; numAllocs < MAX_PLAUSIBLE_ALLOCS; ++numAllocs) { 49 chunks.add(runtime.newNonMovableArray(Object.class, 252)); // About 1KB 50 } 51 // If we get here, we've allocated about 1GB of nonmovable memory, which 52 // should be impossible. 53 } catch (OutOfMemoryError e) { 54 chunks.remove(0); // Give us a little space back. 55 if (((Object[]) (chunks.get(42)))[17] != null) { 56 System.out.println("Bad entry in chunks array"); 57 } else { 58 chunks.clear(); // Recover remaining space. 59 if (SHOULD_PRINT) { 60 System.out.println("Successfully allocated " + numAllocs + " non-movable KBs"); 61 } 62 System.out.println("passed"); 63 } 64 Reference.reachabilityFence(chunks); 65 return; 66 } 67 Reference.reachabilityFence(chunks); 68 System.out.println("Failed to exhaust non-movable space"); 69 } 70 71 // When using the Concurrent Copying (CC) collector (default collector), 72 // this method allocates an object in the non-moving space and an object 73 // in the region space, make the former reference the later, and returns 74 // nothing (so that none of these objects are reachable upon return). $noinline$Alloc(VMRuntime runtime)75 static void $noinline$Alloc(VMRuntime runtime) { 76 Object[] non_moving_array = (Object[]) runtime.newNonMovableArray(Object.class, 1); 77 // Small object, unlikely to trigger garbage collection. 78 non_moving_array[0] = new Object(); 79 } 80 81 } 82