]> WPIA git - gigi.git/blobdiff - lib/jetty/org/eclipse/jetty/util/LeakDetector.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / util / LeakDetector.java
index b0ac94e9b4d0f5cb2cbf2b6b8dc71bafd23c74b0..11b3b31a83a153480e2ac4546d708cd6afeea7bd 100644 (file)
@@ -1,6 +1,6 @@
 //
 //  ========================================================================
-//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+//  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
 //  ------------------------------------------------------------------------
 //  All rights reserved. This program and the accompanying materials
 //  are made available under the terms of the Eclipse Public License v1.0
@@ -31,40 +31,29 @@ import org.eclipse.jetty.util.log.Logger;
 /**
  * A facility to detect improper usage of resource pools.
  * <p>
- * Resource pools usually have a method to acquire a pooled resource
- * and a method to released it back to the pool.
+ * Resource pools usually have a method to acquire a pooled resource and a method to released it back to the pool.
  * <p>
- * To detect if client code acquires a resource but never releases it,
- * the resource pool can be modified to use a {@link LeakDetector}.
- * The modified resource pool should call {@link #acquired(Object)} every time
- * the method to acquire a resource is called, and {@link #released(Object)}
- * every time the method to release the resource is called.
+ * To detect if client code acquires a resource but never releases it, the resource pool can be modified to use a
+ * {@link LeakDetector}. The modified resource pool should call {@link #acquired(Object)} every time the method to
+ * acquire a resource is called, and {@link #released(Object)} every time the method to release the resource is called.
  * {@link LeakDetector} keeps track of these resources and invokes method
- * {@link #leaked(org.eclipse.jetty.util.LeakDetector.LeakInfo)} when it detects that a resource
- * has been leaked (that is, acquired but never released).
+ * {@link #leaked(org.eclipse.jetty.util.LeakDetector.LeakInfo)} when it detects that a resource has been leaked (that
+ * is, acquired but never released).
  * <p>
- * To detect whether client code releases a resource without having
- * acquired it, the resource pool can be modified to check the return value
- * of {@link #released(Object)}: if false, it means that the resource was
- * not acquired.
+ * To detect whether client code releases a resource without having acquired it, the resource pool can be modified to
+ * check the return value of {@link #released(Object)}: if false, it means that the resource was not acquired.
  * <p>
  * IMPLEMENTATION NOTES
  * <p>
- * This class relies on {@link System#identityHashCode(Object)} to create
- * a unique id for each resource passed to {@link #acquired(Object)} and
- * {@link #released(Object)}. {@link System#identityHashCode(Object)} does
- * not guarantee that it will not generate the same number for different
- * objects, but in practice the chance of collision is rare.
+ * This class relies on {@link System#identityHashCode(Object)} to create a unique id for each resource passed to
+ * {@link #acquired(Object)} and {@link #released(Object)}. {@link System#identityHashCode(Object)} does not guarantee
+ * that it will not generate the same number for different objects, but in practice the chance of collision is rare.
  * <p>
- * {@link LeakDetector} uses {@link PhantomReference}s to detect leaks.
- * {@link PhantomReference}s are enqueued in their {@link ReferenceQueue}
- * <em>after</em> they have been garbage collected (differently from
- * {@link WeakReference}s that are enqueued <em>before</em>).
- * Since the resource is now garbage collected, {@link LeakDetector} checks
- * whether it has been released and if not, it reports a leak.
- * Using {@link PhantomReference}s is better than overriding {@link #finalize()}
- * and works also in those cases where {@link #finalize()} is not
- * overridable.
+ * {@link LeakDetector} uses {@link PhantomReference}s to detect leaks. {@link PhantomReference}s are enqueued in their
+ * {@link ReferenceQueue} <em>after</em> they have been garbage collected (differently from {@link WeakReference}s that
+ * are enqueued <em>before</em>). Since the resource is now garbage collected, {@link LeakDetector} checks whether it
+ * has been released and if not, it reports a leak. Using {@link PhantomReference}s is better than overriding
+ * {@link #finalize()} and works also in those cases where {@link #finalize()} is not overridable.
  *
  * @param <T> the resource type.
  */
@@ -80,26 +69,43 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
      * Tracks the resource as been acquired.
      *
      * @param resource the resource that has been acquired
-     * @return whether the resource has been tracked
+     * @return true whether the resource has been acquired normally, false if the resource has detected a leak (meaning
+     *         that another acquire occurred before a release of the same resource)
      * @see #released(Object)
      */
     public boolean acquired(T resource)
     {
         String id = id(resource);
-        return resources.putIfAbsent(id, new LeakInfo(resource, id)) == null;
+        LeakInfo info = resources.putIfAbsent(id, new LeakInfo(resource,id));
+        if (info != null)
+        {
+            // Leak detected, prior acquire exists (not released) or id clash.
+            return false;
+        }
+        // Normal behavior.
+        return true;
     }
 
     /**
      * Tracks the resource as been released.
      *
      * @param resource the resource that has been released
-     * @return whether the resource has been acquired
+     * @return true whether the resource has been released normally (based on a previous acquire). false if the resource
+     *         has been released without a prior acquire (such as a double release scenario)
      * @see #acquired(Object)
      */
     public boolean released(T resource)
     {
         String id = id(resource);
-        return resources.remove(id) != null;
+        LeakInfo info = resources.remove(id);
+        if (info != null)
+        {
+            // Normal behavior.
+            return true;
+        }
+
+        // Leak detected (released without acquire).
+        return false;
     }
 
     /**
@@ -108,7 +114,7 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
      * @param resource the resource to generate the unique ID for
      * @return the unique ID of the given resource
      */
-    protected String id(T resource)
+    public String id(T resource)
     {
         return String.valueOf(System.identityHashCode(resource));
     }
@@ -117,7 +123,7 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
     protected void doStart() throws Exception
     {
         super.doStart();
-        thread = new Thread(this, getClass().getSimpleName());
+        thread = new Thread(this,getClass().getSimpleName());
         thread.setDaemon(true);
         thread.start();
     }
@@ -125,8 +131,8 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
     @Override
     protected void doStop() throws Exception
     {
-        thread.interrupt();
         super.doStop();
+        thread.interrupt();
     }
 
     @Override
@@ -138,7 +144,8 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
             {
                 @SuppressWarnings("unchecked")
                 LeakInfo leakInfo = (LeakInfo)queue.remove();
-                LOG.debug("Resource GC'ed: {}", leakInfo);
+                if (LOG.isDebugEnabled())
+                    LOG.debug("Resource GC'ed: {}",leakInfo);
                 if (resources.remove(leakInfo.id) != null)
                     leaked(leakInfo);
             }
@@ -156,7 +163,7 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
      */
     protected void leaked(LeakInfo leakInfo)
     {
-        LOG.warn("Resource leaked: " + leakInfo.description, leakInfo.stackFrames);
+        LOG.warn("Resource leaked: " + leakInfo.description,leakInfo.stackFrames);
     }
 
     /**
@@ -170,7 +177,7 @@ public class LeakDetector<T> extends AbstractLifeCycle implements Runnable
 
         private LeakInfo(T referent, String id)
         {
-            super(referent, queue);
+            super(referent,queue);
             this.id = id;
             this.description = referent.toString();
             this.stackFrames = new Throwable();