133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler/*
233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * Copyright (C) 2015 The Android Open Source Project
333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *
433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * Licensed under the Apache License, Version 2.0 (the "License");
533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * you may not use this file except in compliance with the License.
633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * You may obtain a copy of the License at
733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *
833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *      http://www.apache.org/licenses/LICENSE-2.0
933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *
1033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * Unless required by applicable law or agreed to in writing, software
1133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * distributed under the License is distributed on an "AS IS" BASIS,
1233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * See the License for the specific language governing permissions and
1433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * limitations under the License
1533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler */
1633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
1733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerpackage libcore.util;
1833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
1933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerimport dalvik.system.VMRuntime;
2033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerimport sun.misc.Cleaner;
2133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
2233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler/**
2333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * A NativeAllocationRegistry is used to associate native allocations with
2433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * Java objects and register them with the runtime.
2533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * There are two primary benefits of registering native allocations associated
2633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * with Java objects:
2733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * <ol>
2833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *  <li>The runtime will account for the native allocations when scheduling
2933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *  garbage collection to run.</li>
3033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *  <li>The runtime will arrange for the native allocation to be automatically
3133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *  freed by a user-supplied function when the associated Java object becomes
3233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler *  unreachable.</li>
3333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * </ol>
3433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * A separate NativeAllocationRegistry should be instantiated for each kind
3533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * of native allocation, where the kind of a native allocation consists of the
3633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * native function used to free the allocation and the estimated size of the
3733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * allocation. Once a NativeAllocationRegistry is instantiated, it can be
3833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * used to register any number of native allocations of that kind.
3933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler * @hide
4033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler */
4133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerpublic class NativeAllocationRegistry {
4233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
43111fdf10801861427f59e42c34c40d5df484053bRichard Uhler    private final ClassLoader classLoader;
4433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private final long freeFunction;
4533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private final long size;
4633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
4733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    /**
4833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Constructs a NativeAllocationRegistry for a particular kind of native
4933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * allocation.
5033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * The address of a native function that can be used to free this kind
5133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * native allocation should be provided using the
5233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <code>freeFunction</code> argument. The native function should have the
5333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * type:
5433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <pre>
5533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *    void f(void* nativePtr);
5633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * </pre>
5733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <p>
58111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * The <code>classLoader</code> argument should be the class loader used
59111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * to load the native library that freeFunction belongs to. This is needed
60111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * to ensure the native library doesn't get unloaded before freeFunction
61111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * is called.
62111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * <p>
6333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * The <code>size</code> should be an estimate of the total number of
6433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * native bytes this kind of native allocation takes up. Different
6533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * NativeAllocationRegistrys must be used to register native allocations
6633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * with different estimated sizes, even if they use the same
6733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <code>freeFunction</code>.
68111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     * @param classLoader  ClassLoader that was used to load the native
69111fdf10801861427f59e42c34c40d5df484053bRichard Uhler     *                     library freeFunction belongs to.
7033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param freeFunction address of a native function used to free this
7133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                     kind of native allocation
7233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param size         estimated size in bytes of this kind of native
7333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                     allocation
7433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @throws IllegalArgumentException If <code>size</code> is negative
7533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     */
76111fdf10801861427f59e42c34c40d5df484053bRichard Uhler    public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
7733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        if (size < 0) {
7833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            throw new IllegalArgumentException("Invalid native allocation size: " + size);
7933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
8033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
81111fdf10801861427f59e42c34c40d5df484053bRichard Uhler        this.classLoader = classLoader;
8233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        this.freeFunction = freeFunction;
8333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        this.size = size;
8433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
8533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
8633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    /**
8733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Registers a new native allocation and associated Java object with the
8833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * runtime.
8933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * This NativeAllocationRegistry's <code>freeFunction</code> will
9033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * automatically be called with <code>nativePtr</code> as its sole
9133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * argument when <code>referent</code> becomes unreachable. If you
9233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * maintain copies of <code>nativePtr</code> outside
9333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <code>referent</code>, you must not access these after
9433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <code>referent</code> becomes unreachable, because they may be dangling
9533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * pointers.
9633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <p>
9733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * The returned Runnable can be used to free the native allocation before
9833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <code>referent</code> becomes unreachable. The runnable will have no
9933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * effect if the native allocation has already been freed by the runtime
10033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * or by using the runnable.
10133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *
10233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param referent      java object to associate the native allocation with
10333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param nativePtr     address of the native allocation
10433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @return runnable to explicitly free native allocation
10533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @throws IllegalArgumentException if either referent or nativePtr is null.
10633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @throws OutOfMemoryError  if there is not enough space on the Java heap
10733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           in which to register the allocation. In this
10833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           case, <code>freeFunction</code> will be
10933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           called with <code>nativePtr</code> as its
11033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           argument before the OutOfMemoryError is
11133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           thrown.
11233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     */
11333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    public Runnable registerNativeAllocation(Object referent, long nativePtr) {
11433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        if (referent == null) {
11533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            throw new IllegalArgumentException("referent is null");
11633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
11733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        if (nativePtr == 0) {
11833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            throw new IllegalArgumentException("nativePtr is null");
11933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
12033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
12133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        try {
12233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            registerNativeAllocation(this.size);
12333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        } catch (OutOfMemoryError oome) {
12433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            applyFreeFunction(freeFunction, nativePtr);
12533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            throw oome;
12633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
12733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
12833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        Cleaner cleaner = Cleaner.create(referent, new CleanerThunk(nativePtr));
12933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        return new CleanerRunner(cleaner);
13033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
13133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
13233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    /**
13333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Interface for custom native allocation allocators used by
13433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * {@link #registerNativeAllocation(Object, Allocator) registerNativeAllocation(Object, Allocator)}.
13533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     */
13633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    public interface Allocator {
13733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        /**
13833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler         * Allocate a native allocation and return its address.
13933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler         */
14033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        long allocate();
14133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
14233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
14333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    /**
14433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Registers and allocates a new native allocation and associated Java
14533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * object with the runtime.
14633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * This can be used for registering large allocations where the underlying
14733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * native allocation shouldn't be performed until it's clear there is
14833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * enough space on the Java heap to register the allocation.
14933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * <p>
15033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * If the allocator returns null, the allocation is not registered and a
15133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * null Runnable is returned.
15233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *
15333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param referent      java object to associate the native allocation with
15433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @param allocator     used to perform the underlying native allocation.
15533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @return runnable to explicitly free native allocation
15633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @throws IllegalArgumentException if referent is null.
15733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * @throws OutOfMemoryError  if there is not enough space on the Java heap
15833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           in which to register the allocation. In this
15933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     *                           case, the allocator will not be run.
16033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     */
16133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    public Runnable registerNativeAllocation(Object referent, Allocator allocator) {
16233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        if (referent == null) {
16333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            throw new IllegalArgumentException("referent is null");
16433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
16533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        registerNativeAllocation(this.size);
16633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
16733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        // Create the cleaner before running the allocator so that
16833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        // VMRuntime.registerNativeFree is eventually called if the allocate
16933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        // method throws an exception.
17033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        CleanerThunk thunk = new CleanerThunk();
17133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        Cleaner cleaner = Cleaner.create(referent, thunk);
17233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        long nativePtr = allocator.allocate();
17333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        if (nativePtr == 0) {
17433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            cleaner.clean();
17533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            return null;
17633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
17733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        thunk.setNativePtr(nativePtr);
17833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        return new CleanerRunner(cleaner);
17933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
18033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
18133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private class CleanerThunk implements Runnable {
18233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        private long nativePtr;
18333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
18433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public CleanerThunk() {
18533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            this.nativePtr = 0;
18633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
18733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
18833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public CleanerThunk(long nativePtr) {
18933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            this.nativePtr = nativePtr;
19033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
19133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
19233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public void run() {
19333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            if (nativePtr != 0) {
19433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler                applyFreeFunction(freeFunction, nativePtr);
19533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            }
19633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            registerNativeFree(size);
19733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
19833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
19933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public void setNativePtr(long nativePtr) {
20033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            this.nativePtr = nativePtr;
20133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
20233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
20333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
20433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private static class CleanerRunner implements Runnable {
20533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        private final Cleaner cleaner;
20633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
20733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public CleanerRunner(Cleaner cleaner) {
20833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            this.cleaner = cleaner;
20933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
21033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
21133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        public void run() {
21233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler            cleaner.clean();
21333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        }
21433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
21533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
21633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    // TODO: Change the runtime to support passing the size as a long instead
21733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    // of an int. For now, we clamp the size to fit.
21833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private static void registerNativeAllocation(long size) {
21933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        VMRuntime.getRuntime().registerNativeAllocation((int)Math.min(size, Integer.MAX_VALUE));
22033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
22133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
22233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    private static void registerNativeFree(long size) {
22333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler        VMRuntime.getRuntime().registerNativeFree((int)Math.min(size, Integer.MAX_VALUE));
22433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    }
22533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
22633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    /**
22733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Calls <code>freeFunction</code>(<code>nativePtr</code>).
22833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * Provided as a convenience in the case where you wish to manually free a
22933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * native allocation using a <code>freeFunction</code> without using a
23033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     * NativeAllocationRegistry.
23133fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler     */
23233fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler    public static native void applyFreeFunction(long freeFunction, long nativePtr);
23333fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler}
23433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
235