]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/io/LeakTrackingByteBufferPool.java
Merge "Update notes about password security"
[gigi.git] / lib / jetty / org / eclipse / jetty / io / LeakTrackingByteBufferPool.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.io;
20
21 import java.nio.ByteBuffer;
22 import java.util.concurrent.atomic.AtomicLong;
23
24 import org.eclipse.jetty.util.BufferUtil;
25 import org.eclipse.jetty.util.LeakDetector;
26 import org.eclipse.jetty.util.component.ContainerLifeCycle;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29
30 public class LeakTrackingByteBufferPool extends ContainerLifeCycle implements ByteBufferPool
31 {
32     private static final Logger LOG = Log.getLogger(LeakTrackingByteBufferPool.class);
33
34     private final LeakDetector<ByteBuffer> leakDetector = new LeakDetector<ByteBuffer>()
35     {
36         public String id(ByteBuffer resource)
37         {
38             return BufferUtil.toIDString(resource);
39         }
40
41         @Override
42         protected void leaked(LeakInfo leakInfo)
43         {
44             leaked.incrementAndGet();
45             LeakTrackingByteBufferPool.this.leaked(leakInfo);
46         }
47     };
48
49     private final static boolean NOISY = Boolean.getBoolean(LeakTrackingByteBufferPool.class.getName() + ".NOISY");
50     private final ByteBufferPool delegate;
51     private final AtomicLong leakedReleases = new AtomicLong(0);
52     private final AtomicLong leakedAcquires = new AtomicLong(0);
53     private final AtomicLong leaked = new AtomicLong(0);
54
55     public LeakTrackingByteBufferPool(ByteBufferPool delegate)
56     {
57         this.delegate = delegate;
58         addBean(leakDetector);
59         addBean(delegate);
60     }
61
62     @Override
63     public ByteBuffer acquire(int size, boolean direct)
64     {
65         ByteBuffer buffer = delegate.acquire(size, direct);
66         boolean leaked = leakDetector.acquired(buffer);
67         if (NOISY || !leaked)
68         {
69             leakedAcquires.incrementAndGet();
70             LOG.info(String.format("ByteBuffer acquire %s leaked.acquired=%s", leakDetector.id(buffer), leaked ? "normal" : "LEAK"),
71                     new Throwable("LeakStack.Acquire"));
72         }
73         return buffer;
74     }
75
76     @Override
77     public void release(ByteBuffer buffer)
78     {
79         if (buffer == null)
80             return;
81         boolean leaked = leakDetector.released(buffer);
82         if (NOISY || !leaked)
83         {
84             leakedReleases.incrementAndGet();
85             LOG.info(String.format("ByteBuffer release %s leaked.released=%s", leakDetector.id(buffer), leaked ? "normal" : "LEAK"), new Throwable(
86                     "LeakStack.Release"));
87         }
88         delegate.release(buffer);
89     }
90
91     public void clearTracking()
92     {
93         leakedAcquires.set(0);
94         leakedReleases.set(0);
95     }
96
97     /**
98      * @return count of BufferPool.acquire() calls that detected a leak
99      */
100     public long getLeakedAcquires()
101     {
102         return leakedAcquires.get();
103     }
104
105     /**
106      * @return count of BufferPool.release() calls that detected a leak
107      */
108     public long getLeakedReleases()
109     {
110         return leakedReleases.get();
111     }
112
113     /**
114      * @return count of resources that were acquired but not released
115      */
116     public long getLeakedResources()
117     {
118         return leaked.get();
119     }
120
121     protected void leaked(LeakDetector<ByteBuffer>.LeakInfo leakInfo)
122     {
123         LOG.warn("ByteBuffer " + leakInfo.getResourceDescription() + " leaked at:", leakInfo.getStackFrames());
124     }
125 }