1f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom/*
2f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project
3f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
4f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * you may not use this file except in compliance with the License.
6f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * You may obtain a copy of the License at
7f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
8f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
10f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
11f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * See the License for the specific language governing permissions and
14f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * limitations under the License.
15f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom */
16f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
17f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrompackage dalvik.system;
18f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
19f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom/**
202353846b64570fa5932028143a0af507d41a85c5Jesse Wilson * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
21f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * resources that should have been cleaned up by explicit close
22f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * methods (aka "explicit termination methods" in Effective Java).
23f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * <p>
24f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * A simple example: <pre>   {@code
25f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *   class Foo {
26f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
2712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       private final CloseGuard guard = CloseGuard.get();
28f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
29f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       ...
30f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
3112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       public Foo() {
3212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *           ...;
3312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *           guard.open("cleanup");
3412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       }
3512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *
36f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       public void cleanup() {
37f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *          guard.close();
38f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *          ...;
39f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       }
40f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
4112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       protected void finalize() throws Throwable {
42f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           try {
4312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *               if (guard != null) {
4412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *                   guard.warnIfOpen();
4512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *               }
46f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *               cleanup();
47f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           } finally {
48f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *               super.finalize();
49f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           }
50f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       }
51f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *   }
52f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * }</pre>
53f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
542353846b64570fa5932028143a0af507d41a85c5Jesse Wilson * In usage where the resource to be explicitly cleaned up are
551292ca6a89af2492f9c1f52f7d4a555c75462482Brian Carlstrom * allocated after object construction, CloseGuard protection can
56f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * be deferred. For example: <pre>   {@code
57f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *   class Bar {
58f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
591292ca6a89af2492f9c1f52f7d4a555c75462482Brian Carlstrom *       private final CloseGuard guard = CloseGuard.get();
60f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
61f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       ...
62f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
6312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       public Bar() {
6412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *           ...;
6512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       }
6612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *
67f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       public void connect() {
68f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *          ...;
6912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *          guard.open("cleanup");
70f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       }
71f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
72f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       public void cleanup() {
73f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *          guard.close();
74f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *          ...;
75f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       }
76f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
7712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *       protected void finalize() throws Throwable {
78f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           try {
7912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *               if (guard != null) {
8012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *                   guard.warnIfOpen();
8112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *               }
82f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *               cleanup();
83f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           } finally {
84f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *               super.finalize();
85f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *           }
86f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *       }
87f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *   }
88f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * }</pre>
89f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom *
9012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * When used in a constructor calls to {@code open} should occur at
9112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * the end of the constructor since an exception that would cause
9212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * abrupt termination of the constructor will mean that the user will
9312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * not have a reference to the object to cleanup explicitly. When used
9412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * in a method, the call to {@code open} should occur just after
9512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * resource acquisition.
9612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *
9712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * <p>
9812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *
9912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * Note that the null check on {@code guard} in the finalizer is to
10012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * cover cases where a constructor throws an exception causing the
10112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom * {@code guard} to be uninitialized.
10212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom *
103f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom * @hide
104f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom */
105f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrompublic final class CloseGuard {
106f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
107f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    /**
108f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * Instance used when CloseGuard is disabled to avoid allocation.
109f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     */
110f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    private static final CloseGuard NOOP = new CloseGuard();
111f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
112f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    /**
1134bfc26e99c8044a1d690003d4bb3d75348124f57Brad Fitzpatrick     * Enabled by default so we can catch issues early in VM startup.
1144bfc26e99c8044a1d690003d4bb3d75348124f57Brad Fitzpatrick     * Note, however, that Android disables this early in its startup,
1154bfc26e99c8044a1d690003d4bb3d75348124f57Brad Fitzpatrick     * but enables it with DropBoxing for system apps on debug builds.
116b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom     */
1174bfc26e99c8044a1d690003d4bb3d75348124f57Brad Fitzpatrick    private static volatile boolean ENABLED = true;
118b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom
119b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom    /**
120f7ee236589ca1fe73615c4dc8a536ffe29a236ffBrian Carlstrom     * Hook for customizing how CloseGuard issues are reported.
121b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     */
1224bfc26e99c8044a1d690003d4bb3d75348124f57Brad Fitzpatrick    private static volatile Reporter REPORTER = new DefaultReporter();
123b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom
124b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    /**
12512f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom     * Returns a CloseGuard instance. If CloseGuard is enabled, {@code
12612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom     * #open(String)} can be used to set up the instance to warn on
12712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom     * failure to close. If CloseGuard is disabled, a non-null no-op
1282353846b64570fa5932028143a0af507d41a85c5Jesse Wilson     * instance is returned.
129f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     */
13012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom    public static CloseGuard get() {
131b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom        if (!ENABLED) {
132f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            return NOOP;
133f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        }
134f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        return new CloseGuard();
135f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
136f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
137b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom    /**
138b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom     * Used to enable or disable CloseGuard. Note that CloseGuard only
139b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom     * warns if it is enabled for both allocation and finalization.
140b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom     */
141b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom    public static void setEnabled(boolean enabled) {
142b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom        ENABLED = enabled;
143f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
144f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
145b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    /**
146b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     * Used to replace default Reporter used to warn of CloseGuard
147b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     * violations. Must be non-null.
148b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     */
149b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    public static void setReporter(Reporter reporter) {
150b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        if (reporter == null) {
151b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom            throw new NullPointerException("reporter == null");
152b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        }
153b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        REPORTER = reporter;
154b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    }
155b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom
156b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    /**
157b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     * Returns non-null CloseGuard.Reporter.
158b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     */
159b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    public static Reporter getReporter() {
160b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        return REPORTER;
161b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    }
162b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom
163f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    private CloseGuard() {}
164f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
165f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    /**
166f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * If CloseGuard is enabled, {@code open} initializes the instance
1672353846b64570fa5932028143a0af507d41a85c5Jesse Wilson     * with a warning that the caller should have explicitly called the
168f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * {@code closer} method instead of relying on finalization.
169f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     *
1702353846b64570fa5932028143a0af507d41a85c5Jesse Wilson     * @param closer non-null name of explicit termination method
171f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * @throws NullPointerException if closer is null, regardless of
172f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * whether or not CloseGuard is enabled
173f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     */
174f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    public void open(String closer) {
175f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        // always perform the check for valid API usage...
176f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        if (closer == null) {
177f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            throw new NullPointerException("closer == null");
178f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        }
179f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        // ...but avoid allocating an allocationSite if disabled
180b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom        if (this == NOOP || !ENABLED) {
181f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            return;
182f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        }
183f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        String message = "Explicit termination method '" + closer + "' not called";
184f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        allocationSite = new Throwable(message);
185f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
186f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
187f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    private Throwable allocationSite;
188f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
189f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    /**
190f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * Marks this CloseGuard instance as closed to avoid warnings on
191f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * finalization.
192f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     */
193f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    public void close() {
194f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        allocationSite = null;
195f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
196f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
197f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    /**
198f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * If CloseGuard is enabled, logs a warning if the caller did not
199f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * properly cleanup by calling an explicit close method
2008155888a2c4e7cc28596deec28433e1984cfaf11Brian Carlstrom     * before finalization. If CloseGuard is disabled, no action is
201f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     * performed.
202f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom     */
203f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    public void warnIfOpen() {
204b3f32d4d15177a0d2c064a8116d5cf5d07a217a9Brian Carlstrom        if (allocationSite == null || !ENABLED) {
205f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            return;
206f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        }
207f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
208f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        String message =
209f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                ("A resource was acquired at attached stack trace but never released. "
210f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom                 + "See java.io.Closeable for information on avoiding resource leaks.");
211f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
212b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        REPORTER.report(message, allocationSite);
213b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    }
214b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom
215b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    /**
216b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     * Interface to allow customization of reporting behavior.
217b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     */
218b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    public static interface Reporter {
219b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        public void report (String message, Throwable allocationSite);
220b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    }
221b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom
222b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    /**
223a7ef55258ac71153487357b861c7639d627df82fElliott Hughes     * Default Reporter which reports CloseGuard violations to the log.
224b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom     */
225b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom    private static final class DefaultReporter implements Reporter {
2268155888a2c4e7cc28596deec28433e1984cfaf11Brian Carlstrom        @Override public void report (String message, Throwable allocationSite) {
227a7ef55258ac71153487357b861c7639d627df82fElliott Hughes            System.logW(message, allocationSite);
228b81e1d9da6a4b039ffa55618fcccb013d3116261Brian Carlstrom        }
229f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
230f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom}
231