@@ -41,8 +41,13 @@ public class ThreadLocalCleaner {
41
41
/** this field is in class {@code ThreadLocal.ThreadLocalMap.Entry} and contains an object referencing the actual thread local
42
42
* variable */
43
43
private static Field threadLocalEntryValueField ;
44
+ /** this field is in the class {@code ThreadLocal.ThreadLocalMap} and contains the number of the entries */
45
+ private static Field threadLocalMapSizeField ;
46
+ /** this field is in the class {@code ThreadLocal.ThreadLocalMap} and next resize threshold */
47
+ private static Field threadLocalMapThresholdField ;
44
48
private static IllegalStateException reflectionException ;
45
49
50
+
46
51
public ThreadLocalCleaner (ThreadLocalChangeListener listener ) {
47
52
if (threadLocalsField == null ) {
48
53
initReflectionFields ();
@@ -65,6 +70,8 @@ private static synchronized void initReflectionFields() throws IllegalStateExcep
65
70
tableField = field (threadLocalMapClass , "table" );
66
71
threadLocalMapEntryClass = inner (threadLocalMapClass , "Entry" );
67
72
threadLocalEntryValueField = field (threadLocalMapEntryClass , "value" );
73
+ threadLocalMapSizeField = field (threadLocalMapClass , "size" );
74
+ threadLocalMapThresholdField = field (threadLocalMapClass , "threshold" );
68
75
} catch (NoSuchFieldException e ) {
69
76
reflectionException = new IllegalStateException (
70
77
"Could not locate threadLocals field in class Thread. " +
@@ -169,12 +176,19 @@ private static Class<?> inner(Class<?> clazz, String name) {
169
176
}
170
177
171
178
private static final ThreadLocal <Reference <?>[]> copyOfThreadLocals = new ThreadLocal <>();
172
-
179
+ private static final ThreadLocal <Integer > copyOfThreadLocalsSize = new ThreadLocal <>();
180
+ private static final ThreadLocal <Integer > copyOfThreadLocalsThreshold = new ThreadLocal <>();
173
181
private static final ThreadLocal <Reference <?>[]> copyOfInheritableThreadLocals = new ThreadLocal <>();
182
+ private static final ThreadLocal <Integer > copyOfInheritableThreadLocalsSize = new ThreadLocal <>();
183
+ private static final ThreadLocal <Integer > copyOfInheritableThreadLocalsThreshold = new ThreadLocal <>();
174
184
175
185
private static void saveOldThreadLocals () {
176
186
copyOfThreadLocals .set (copy (threadLocalsField ));
187
+ copyOfThreadLocalsSize .set (size (threadLocalsField , threadLocalMapSizeField ));
188
+ copyOfThreadLocalsThreshold .set (size (threadLocalsField , threadLocalMapThresholdField ));
177
189
copyOfInheritableThreadLocals .set (copy (inheritableThreadLocalsField ));
190
+ copyOfInheritableThreadLocalsSize .set (size (inheritableThreadLocalsField , threadLocalMapSizeField ));
191
+ copyOfInheritableThreadLocalsThreshold .set (size (inheritableThreadLocalsField , threadLocalMapThresholdField ));
178
192
}
179
193
180
194
private static Reference <?>[] copy (Field field ) {
@@ -190,31 +204,43 @@ private static Reference<?>[] copy(Field field) {
190
204
}
191
205
}
192
206
207
+ private static Integer size (Field field , Field sizeField ) {
208
+ try {
209
+ Thread thread = Thread .currentThread ();
210
+ Object threadLocals = field .get (thread );
211
+ if (threadLocals == null )
212
+ return null ;
213
+ return (Integer ) sizeField .get (threadLocals );
214
+ } catch (IllegalAccessException e ) {
215
+ throw new IllegalStateException ("Access denied" , e );
216
+ }
217
+ }
218
+
193
219
private static void restoreOldThreadLocals () {
194
220
try {
195
- restore (inheritableThreadLocalsField , copyOfInheritableThreadLocals .get ());
196
- restore (threadLocalsField , copyOfThreadLocals .get ());
221
+ restore (inheritableThreadLocalsField , copyOfInheritableThreadLocals .get (),
222
+ copyOfInheritableThreadLocalsSize .get (), copyOfInheritableThreadLocalsThreshold .get ());
223
+ restore (threadLocalsField , copyOfThreadLocals .get (),
224
+ copyOfThreadLocalsSize .get (), copyOfThreadLocalsThreshold .get ());
197
225
} finally {
198
226
copyOfThreadLocals .remove ();
199
227
copyOfInheritableThreadLocals .remove ();
200
228
}
201
229
}
202
230
203
- private static void restore (Field field , Object value ) {
231
+ private static void restore (Field field , Object value , Integer size , Integer threshold ) {
204
232
try {
205
233
Thread thread = Thread .currentThread ();
206
234
if (value == null ) {
207
235
field .set (thread , null );
208
236
} else {
209
- tableField .set (field .get (thread ), value );
237
+ final Object threadLocals = field .get (thread );
238
+ tableField .set (threadLocals , value );
239
+ threadLocalMapSizeField .set (threadLocals , size );
240
+ threadLocalMapThresholdField .set (threadLocals , threshold );
210
241
}
211
242
} catch (IllegalAccessException e ) {
212
243
throw new IllegalStateException ("Access denied" , e );
213
244
}
214
245
}
215
-
216
- static {
217
- // TODO: move to a place where the exception can be caught!
218
-
219
- }
220
246
}
0 commit comments