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