1/* 2 * Copyright (C) 2013 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.*; 18import java.lang.Runtime; 19 20public class Main { 21 static Object nativeLock = new Object(); 22 static Object deadlockLock = new Object(); 23 static boolean aboutToDeadlockLock = false; 24 static int nativeBytes = 0; 25 static Object runtime; 26 static Method register_native_allocation; 27 static Method register_native_free; 28 static long maxMem = 0; 29 30 static class NativeAllocation { 31 private int bytes; 32 33 NativeAllocation(int bytes, boolean testingDeadlock) throws Exception { 34 this.bytes = bytes; 35 register_native_allocation.invoke(runtime, bytes); 36 synchronized (nativeLock) { 37 if (!testingDeadlock) { 38 nativeBytes += bytes; 39 if (nativeBytes > maxMem) { 40 throw new OutOfMemoryError(); 41 } 42 } 43 } 44 } 45 46 protected void finalize() throws Exception { 47 synchronized (nativeLock) { 48 nativeBytes -= bytes; 49 } 50 register_native_free.invoke(runtime, bytes); 51 aboutToDeadlockLock = true; 52 synchronized (deadlockLock) { 53 } 54 } 55 } 56 57 public static void main(String[] args) throws Exception { 58 Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime"); 59 Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime"); 60 runtime = get_runtime.invoke(null); 61 register_native_allocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE); 62 register_native_free = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE); 63 maxMem = Runtime.getRuntime().maxMemory(); 64 int count = 16; 65 int size = (int)(maxMem / 2 / count); 66 int allocation_count = 256; 67 NativeAllocation[] allocations = new NativeAllocation[count]; 68 for (int i = 0; i < allocation_count; ++i) { 69 allocations[i % count] = new NativeAllocation(size, false); 70 } 71 // Test that we don't get a deadlock if we are holding nativeLock. If there is no timeout, 72 // then we will get a finalizer timeout exception. 73 aboutToDeadlockLock = false; 74 synchronized (deadlockLock) { 75 for (int i = 0; aboutToDeadlockLock != true; ++i) { 76 allocations[i % count] = new NativeAllocation(size, true); 77 } 78 // Do more allocations now that the finalizer thread is deadlocked so that we force 79 // finalization and timeout. 80 for (int i = 0; i < 10; ++i) { 81 allocations[i % count] = new NativeAllocation(size, true); 82 } 83 } 84 System.out.println("Test complete"); 85 } 86} 87 88