Commit 4274887
committed
Stop the buffer pool pruner thread when the pool is empty
PROBLEM
The driver starts a thread that removes idle buffers from
PowerOfTwoBufferPool.DEFAULT. That thread never stops. A thread that
runs forever keeps the class loader of all driver classes in memory. The
static data of those classes also stays in memory. Then an application
server cannot unload an application, and the memory of that application
stays in use. Users report this behavior in GitHub issue 2029 and in
JAVA-5643.
CAUSE
DEFAULT is a static field, and it calls enablePruning() during class
initialization. That method schedules a periodic task. The executor
starts the worker thread for the first task, but the pool is empty at
that time. Therefore the thread has no work, and it continues to wake up
forever.
The thread keeps the class loader in memory because the JVM captures the
class loader when it constructs the thread. The data that the thread
holds is not the cause. For this reason, a change to the references of
the thread cannot release the class loader. The thread must stop.
SOLUTION
enablePruning() now sets a flag. It does not schedule a task. The
release() method schedules one prune when it puts a buffer into the
pool. Each prune schedules the next prune, but only if the pool still
holds a buffer. The pruner does not schedule the next prune when the
pool becomes empty.
The pruner also uses these settings on its executor:
- allowCoreThreadTimeOut(true), so that the worker thread can stop
- a keep-alive time of maxIdleTime / 2
- setRemoveOnCancelPolicy(true)
The work queue becomes empty after the last prune. Then the keep-alive
time expires, and the worker thread stops. A later call to release()
schedules a new prune, and the executor starts a new thread.
Two threads must not schedule a prune at the same time. A prune must
also not stop while a different thread adds a buffer to the pool. The
AtomicBoolean pruningScheduled prevents both conditions. The prune
clears the flag, and then it examines the pool one more time before it
stops.
DRAWBACKS
The pool releases the class loader about 90 seconds after the last
buffer release. The default value of maxIdleTime is one minute. A buffer
is old enough to remove only after two prunes, and the keep-alive time
adds 30 seconds. The class loader stays in memory during that period. A
tool that examines threads at the moment of an undeployment can still
find a live thread.
A pool that becomes idle and then busy starts a new thread. This adds a
small cost. A test measures this cost. A busy pool keeps one thread,
because new work arrives before the keep-alive time expires.
prune() keeps its current behavior after an error. It writes a log
message and throws the error again, and the pruner does not start again.
This behavior is the same as before this change.
PRIOR ART
Netty has the same problem and uses the same solution.
GlobalEventExecutor is a single-thread singleton. It starts its thread
when work arrives, and it stops the thread when the task queue stays
empty for a quiet period. The deprecated ThreadDeathWatcher class uses
the same pattern. The steps that this change uses to clear and then
examine the flag follow GlobalEventExecutor.TaskRunner.
Netty also sets the context class loader of a new thread to null. See
netty#7290 and JDK-7008595. That change corrects a different problem,
which is a driver thread that keeps an application class loader in
memory. This commit does not include that change.
TESTS
New tests in PowerOfTwoBufferPoolTest show three results. An empty pool
starts no thread. The thread stops after the pruner empties the pool.
The pruner starts again after the thread stops.
A separate test harness measures class loader retention. That harness
loads the driver into a child class loader, opens a MongoClient, closes
it, and then waits for the class loader to become unreachable. Before
this change, the class loader stayed in memory. After this change, the
JVM collects it. The harness is a local development tool, and it is not
part of this commit.
JAVA-62791 parent d751950 commit 4274887
2 files changed
Lines changed: 186 additions & 8 deletions
File tree
- driver-core/src
- main/com/mongodb/internal/connection
- test/unit/com/mongodb/internal/connection
Lines changed: 106 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
32 | | - | |
| 31 | + | |
| 32 | + | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
43 | 51 | | |
44 | 52 | | |
45 | 53 | | |
| |||
63 | 71 | | |
64 | 72 | | |
65 | 73 | | |
66 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
67 | 81 | | |
68 | 82 | | |
69 | 83 | | |
| |||
96 | 110 | | |
97 | 111 | | |
98 | 112 | | |
99 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
100 | 127 | | |
101 | 128 | | |
102 | 129 | | |
103 | | - | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
104 | 134 | | |
105 | 135 | | |
106 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
107 | 142 | | |
108 | 143 | | |
109 | 144 | | |
110 | 145 | | |
| 146 | + | |
111 | 147 | | |
112 | 148 | | |
113 | 149 | | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
114 | 158 | | |
115 | 159 | | |
116 | 160 | | |
| |||
136 | 180 | | |
137 | 181 | | |
138 | 182 | | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
139 | 234 | | |
| 235 | + | |
140 | 236 | | |
141 | 237 | | |
142 | 238 | | |
| |||
204 | 300 | | |
205 | 301 | | |
206 | 302 | | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
207 | 307 | | |
208 | 308 | | |
Lines changed: 80 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| 30 | + | |
29 | 31 | | |
30 | 32 | | |
31 | 33 | | |
| |||
75 | 77 | | |
76 | 78 | | |
77 | 79 | | |
78 | | - | |
79 | 80 | | |
80 | 81 | | |
81 | 82 | | |
| |||
84 | 85 | | |
85 | 86 | | |
86 | 87 | | |
87 | | - | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
88 | 91 | | |
89 | 92 | | |
90 | 93 | | |
91 | 94 | | |
92 | 95 | | |
93 | 96 | | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
94 | 172 | | |
0 commit comments