Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffa84e00 authored by Hans Boehm's avatar Hans Boehm
Browse files

Reduce risk of memory corruption due to finalization.

Many classes in graphics/java and elsewhere deallocate native memory
in a finalizer on the assumption that instance methods can no longer
be called once the finalizer has been called.  This is incorrect if
the object can be used, possibly indirectly, from another finalizer,
possibly one in the application.

This is the initial installment of a patch to cause such post-finalization
uses to at least see a null pointer rather than causing memory corruption
by accessing deallocated native memory. This should make it possible to
identify and fix such finalization ordering issues.

There are more graphics classes that need this treatment, and probably
many more in other subsystems.

This solution is < 100% effective if finalizers can be invoked
concurrently.  We currently promise that they aren't.

(In my opinion, the real cause here is a language spec bug.  But that ship
has sailed.)

Bug: 18178237
Change-Id: I844cf1e0fbb190407389c4f8e8f072752cca6198
parent 596fd38a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -147,11 +147,12 @@ public class Interpolator {
    @Override
    protected void finalize() throws Throwable {
        nativeDestructor(native_instance);
        native_instance = 0;  // Other finalizers can still call us.
    }
    
    private int mValueCount;
    private int mFrameCount;
    private final long native_instance;
    private long native_instance;

    private static native long nativeConstructor(int valueCount, int frameCount);
    private static native void nativeDestructor(long native_instance);
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ public class MaskFilter {

    protected void finalize() throws Throwable {
        nativeDestructor(native_instance);
        native_instance = 0;  // Other finalizers can still call us.
    }

    private static native void nativeDestructor(long native_filter);
+1 −0
Original line number Diff line number Diff line
@@ -827,6 +827,7 @@ public class Matrix {
    protected void finalize() throws Throwable {
        try {
            finalizer(native_instance);
            native_instance = 0;  // Other finalizers can still call us.
        } finally {
            super.finalize();
        }
+2 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ public class NinePatch {
     *
     * @hide
     */
    public final long mNativeChunk;
    public long mNativeChunk;

    private Paint mPaint;
    private String mSrcName;
@@ -121,6 +121,7 @@ public class NinePatch {
            if (mNativeChunk != 0) {
                // only attempt to destroy correctly initilized chunks
                nativeFinalize(mNativeChunk);
                mNativeChunk = 0;
            }
        } finally {
            super.finalize();
+1 −0
Original line number Diff line number Diff line
@@ -2219,6 +2219,7 @@ public class Paint {
    protected void finalize() throws Throwable {
        try {
            finalizer(mNativePaint);
            mNativePaint = 0;
        } finally {
            super.finalize();
        }
Loading