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
56 lines
1.9 KiB
Java
56 lines
1.9 KiB
Java
/*
|
|
* Copyright (C) 2006 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.graphics;
|
|
|
|
public class RegionIterator {
|
|
|
|
/**
|
|
* Construct an iterator for all of the rectangles in a region. This
|
|
* effectively makes a private copy of the region, so any subsequent edits
|
|
* to region will not affect the iterator.
|
|
*
|
|
* @param region the region that will be iterated
|
|
*/
|
|
public RegionIterator(Region region) {
|
|
mNativeIter = nativeConstructor(region.ni());
|
|
}
|
|
|
|
/**
|
|
* Return the next rectangle in the region. If there are no more rectangles
|
|
* this returns false and r is unchanged. If there is at least one more,
|
|
* this returns true and r is set to that rectangle.
|
|
*/
|
|
public final boolean next(Rect r) {
|
|
if (r == null) {
|
|
throw new NullPointerException("The Rect must be provided");
|
|
}
|
|
return nativeNext(mNativeIter, r);
|
|
}
|
|
|
|
protected void finalize() throws Throwable {
|
|
nativeDestructor(mNativeIter);
|
|
mNativeIter = 0; // Other finalizers can still call us.
|
|
}
|
|
|
|
private static native long nativeConstructor(long native_region);
|
|
private static native void nativeDestructor(long native_iter);
|
|
private static native boolean nativeNext(long native_iter, Rect r);
|
|
|
|
private long mNativeIter;
|
|
}
|
|
|