1 /*
2  * Copyright (C) 2024 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 package libcore.util;
17 
18 import com.android.ravenwood.common.RavenwoodRuntimeNative;
19 
20 import java.lang.ref.Cleaner;
21 import java.lang.ref.Reference;
22 
23 /**
24  * Re-implementation of ART's NativeAllocationRegistry for Ravenwood.
25  * - We don't track the native allocation size on Ravenwood.
26  * - sun.misc.Cleaner isn't available on the desktop JVM, so we use java.lang.ref.Cleaner.
27  *   (Should ART switch to java.lang.ref.Cleaner?)
28  */
29 public class NativeAllocationRegistry {
30     private final long mFreeFunction;
31     private static final Cleaner sCleaner = Cleaner.create();
32 
createNonmalloced( ClassLoader classLoader, long freeFunction, long size)33     public static NativeAllocationRegistry createNonmalloced(
34             ClassLoader classLoader, long freeFunction, long size) {
35         return new NativeAllocationRegistry(classLoader, freeFunction, size, false);
36     }
37 
createMalloced( ClassLoader classLoader, long freeFunction, long size)38     public static NativeAllocationRegistry createMalloced(
39             ClassLoader classLoader, long freeFunction, long size) {
40         return new NativeAllocationRegistry(classLoader, freeFunction, size, true);
41     }
42 
createMalloced( ClassLoader classLoader, long freeFunction)43     public static NativeAllocationRegistry createMalloced(
44             ClassLoader classLoader, long freeFunction) {
45         return new NativeAllocationRegistry(classLoader, freeFunction, 0, true);
46     }
47 
NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size)48     public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
49         this(classLoader, freeFunction, size, size == 0);
50     }
51 
NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size, boolean mallocAllocation)52     private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size,
53             boolean mallocAllocation) {
54         if (size < 0) {
55             throw new IllegalArgumentException("Invalid native allocation size: " + size);
56         }
57         mFreeFunction = freeFunction;
58     }
59 
registerNativeAllocation(Object referent, long nativePtr)60     public Runnable registerNativeAllocation(Object referent, long nativePtr) {
61         if (referent == null) {
62             throw new IllegalArgumentException("referent is null");
63         }
64         if (nativePtr == 0) {
65             throw new IllegalArgumentException("nativePtr is null");
66         }
67 
68         final Runnable releaser = () -> {
69             RavenwoodRuntimeNative.applyFreeFunction(mFreeFunction, nativePtr);
70         };
71         sCleaner.register(referent, releaser);
72 
73         // Ensure that cleaner doesn't get invoked before we enable it.
74         Reference.reachabilityFence(referent);
75         return releaser;
76     }
77 }
78