///////////////////////////////////////////////////////////////////////////////////////////////
-static void Shader_safeUnref(JNIEnv* env, jobject o, jlong shaderHandle) {
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
+static void Shader_safeUnref(SkShader* shader) {
SkSafeUnref(shader);
}
+static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
};
static const JNINativeMethod gShaderMethods[] = {
- { "nativeSafeUnref", "(J)V", (void*)Shader_safeUnref },
+ { "nativeGetFinalizer", "()J", (void*)Shader_getNativeFinalizer },
};
static const JNINativeMethod gBitmapShaderMethods[] = {
import android.annotation.NonNull;
import android.annotation.Nullable;
+import libcore.util.NativeAllocationRegistry;
+
/**
* Shader is the based class for objects that return horizontal spans of colors
* during drawing. A subclass of Shader is installed in a Paint calling
* drawn with that paint will get its color(s) from the shader.
*/
public class Shader {
+
+ private static class NoImagePreloadHolder {
+ public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ Shader.class.getClassLoader(), nativeGetFinalizer(), 50);
+ }
+
/**
* @deprecated Use subclass constructors directly instead.
*/
* is called - otherwise may be out of date with java setters/properties.
*/
private long mNativeInstance;
+ // Runnable to do immediate destruction
+ private Runnable mCleaner;
/**
* Current matrix - always set to null if local matrix is identity.
return 0;
}
- void discardNativeInstance() {
+ /** @hide */
+ protected final void discardNativeInstance() {
if (mNativeInstance != 0) {
- nativeSafeUnref(mNativeInstance);
+ mCleaner.run();
+ mCleaner = null;
mNativeInstance = 0;
}
}
/**
* Callback for subclasses to call {@link #discardNativeInstance()} if the most recently
* constructed native instance is no longer valid.
+ * @hide
*/
- void verifyNativeInstance() {
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mNativeInstance != 0) {
- nativeSafeUnref(mNativeInstance);
- }
- mNativeInstance = -1;
- } finally {
- super.finalize();
- }
+ protected void verifyNativeInstance() {
}
/**
/**
* @hide
*/
- public long getNativeInstance() {
- if (mNativeInstance == -1) {
- throw new IllegalStateException("attempting to use a finalized Shader");
- }
-
+ public final long getNativeInstance() {
// verify mNativeInstance is valid
verifyNativeInstance();
if (mNativeInstance == 0) {
mNativeInstance = createNativeInstance(mLocalMatrix == null
? 0 : mLocalMatrix.native_instance);
+ mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstance);
}
return mNativeInstance;
}
- private static native void nativeSafeUnref(long nativeInstance);
+ private static native long nativeGetFinalizer();
+
}
+