diff options
| author | David Su <dysu@google.com> | 2019-12-06 15:14:17 -0800 |
|---|---|---|
| committer | David Su <dysu@google.com> | 2019-12-10 13:46:24 -0800 |
| commit | 0c472adb0da27c607385fc4587edca741ca2dee3 (patch) | |
| tree | 22cf3ea896dae868de489d29c5a084a9af406a9a /core/java/android/util | |
| parent | d915fc70251dc9fa76c93887de476f05f89f4db4 (diff) | |
Expose CloseGuard as a public API
Wrap dalvik.system.CloseGuard and expose it as a
public API from android.util.
Bug: 145831809
Test: atest CloseGuardTest
Change-Id: Ia44c84a69a5fb693fb8bb1a075c18a60253cedfc
Diffstat (limited to 'core/java/android/util')
| -rw-r--r-- | core/java/android/util/CloseGuard.java | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java new file mode 100644 index 000000000000..c39a6c9aac93 --- /dev/null +++ b/core/java/android/util/CloseGuard.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2019 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.util; + +import android.annotation.NonNull; + +/** + * CloseGuard is a mechanism for flagging implicit finalizer cleanup of + * resources that should have been cleaned up by explicit close + * methods (aka "explicit termination methods" in Effective Java). + * <p> + * A simple example: <pre> {@code + * class Foo { + * + * private final CloseGuard guard = CloseGuard.get(); + * + * ... + * + * public Foo() { + * ...; + * guard.open("cleanup"); + * } + * + * public void cleanup() { + * guard.close(); + * ...; + * } + * + * protected void finalize() throws Throwable { + * try { + * // Note that guard could be null if the constructor threw. + * if (guard != null) { + * guard.warnIfOpen(); + * } + * cleanup(); + * } finally { + * super.finalize(); + * } + * } + * } + * }</pre> + * + * In usage where the resource to be explicitly cleaned up is + * allocated after object construction, CloseGuard protection can + * be deferred. For example: <pre> {@code + * class Bar { + * + * private final CloseGuard guard = CloseGuard.get(); + * + * ... + * + * public Bar() { + * ...; + * } + * + * public void connect() { + * ...; + * guard.open("cleanup"); + * } + * + * public void cleanup() { + * guard.close(); + * ...; + * Reference.reachabilityFence(this); + * // For full correctness in the absence of a close() call, other methods may also need + * // reachabilityFence() calls. + * } + * + * protected void finalize() throws Throwable { + * try { + * // Note that guard could be null if the constructor threw. + * if (guard != null) { + * guard.warnIfOpen(); + * } + * cleanup(); + * } finally { + * super.finalize(); + * } + * } + * } + * }</pre> + * + * When used in a constructor, calls to {@code open} should occur at + * the end of the constructor since an exception that would cause + * abrupt termination of the constructor will mean that the user will + * not have a reference to the object to cleanup explicitly. When used + * in a method, the call to {@code open} should occur just after + * resource acquisition. + */ +public final class CloseGuard { + private final dalvik.system.CloseGuard mImpl; + + /** + * Constructs a new CloseGuard instance. + * {@link #open(String)} can be used to set up the instance to warn on failure to close. + */ + public CloseGuard() { + mImpl = dalvik.system.CloseGuard.get(); + } + + /** + * Initializes the instance with a warning that the caller should have explicitly called the + * {@code closeMethodName} method instead of relying on finalization. + * + * @param closeMethodName non-null name of explicit termination method. Printed by warnIfOpen. + * @throws NullPointerException if closeMethodName is null. + */ + public void open(@NonNull String closeMethodName) { + mImpl.open(closeMethodName); + } + + /** Marks this CloseGuard instance as closed to avoid warnings on finalization. */ + public void close() { + mImpl.close(); + } + + /** + * Logs a warning if the caller did not properly cleanup by calling an explicit close method + * before finalization. + */ + public void warnIfOpen() { + mImpl.warnIfOpen(); + } +} |
