Skip to content

Commit 54fd6d6

Browse files
committed
Partial fix/workaround for #489: add TypeFactory.clearCache()
1 parent d2af373 commit 54fd6d6

File tree

4 files changed

+48
-29
lines changed

4 files changed

+48
-29
lines changed

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Version: 2.4.1 (xx-Jun-2014)
55
(reported by huxi@github)
66
#482: Make date parsing error behavior consistent with JDK
77
(suggested by Steve S, sanbeg@github)
8+
#489 (partial): TypeFactory cache prevents garbage collection of custom ClassLoader
9+
(reported by sftwrengnr@github)
810

911
------------------------------------------------------------------------
1012
=== History: ===

src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java

+17
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ protected TypeFactory(TypeParser p, TypeModifier[] mods) {
115115

116116
public TypeFactory withModifier(TypeModifier mod)
117117
{
118+
if (mod == null) { // mostly for unit tests
119+
return new TypeFactory(_parser, _modifiers);
120+
}
118121
if (_modifiers == null) {
119122
return new TypeFactory(_parser, new TypeModifier[] { mod });
120123
}
@@ -128,6 +131,20 @@ public TypeFactory withModifier(TypeModifier mod)
128131
*/
129132
public static TypeFactory defaultInstance() { return instance; }
130133

134+
/**
135+
* Method that will clear up any cached type definitions that may
136+
* be cached by this {@link TypeFactory} instance.
137+
* This method should not be commonly used, that is, only use it
138+
* if you know there is a problem with retention of type definitions;
139+
* the most likely (and currently only known) problem is retention
140+
* of {@link Class} instances via {@link JavaType} reference.
141+
*
142+
* @since 2.4.1
143+
*/
144+
public void clearCache() {
145+
_typeCache.clear();
146+
}
147+
131148
/*
132149
/**********************************************************
133150
/* Static methods for non-instance-specific functionality

src/main/java/com/fasterxml/jackson/databind/util/LRUMap.java

+15
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ public V remove(Object key) {
8080
_writeLock.unlock();
8181
}
8282
}
83+
84+
/**
85+
* Overridden to allow concurrent way of removing all cached entries.
86+
*
87+
* @since 2.4.1
88+
*/
89+
@Override
90+
public void clear() {
91+
_writeLock.lock();
92+
try {
93+
super.clear();
94+
} finally {
95+
_writeLock.unlock();
96+
}
97+
}
8398

8499
/*
85100
/**********************************************************

src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java

+14-29
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@ public void testIterator()
193193
/**
194194
* Test for verifying that parametric types can be constructed
195195
* programmatically
196-
*
197-
* @since 1.5
198196
*/
199197
public void testParametricTypes()
200198
{
@@ -277,10 +275,7 @@ public void testCanonicalNames()
277275
/* Unit tests: low-level inheritance resolution
278276
/**********************************************************
279277
*/
280-
281-
/**
282-
* @since 1.6
283-
*/
278+
284279
public void testSuperTypeDetectionClass()
285280
{
286281
TypeFactory tf = TypeFactory.defaultInstance();
@@ -294,10 +289,7 @@ public void testSuperTypeDetectionClass()
294289
assertSame(HashMap.class, sup2.getRawClass());
295290
assertNull(sup2.getSuperType());
296291
}
297-
298-
/**
299-
* @since 1.6
300-
*/
292+
301293
public void testSuperTypeDetectionInterface()
302294
{
303295
// List first
@@ -324,9 +316,6 @@ public void testSuperTypeDetectionInterface()
324316
assertNull(sup2.getSuperType());
325317
}
326318

327-
/**
328-
* @since 1.6
329-
*/
330319
public void testAtomicArrayRefParameterDetection()
331320
{
332321
TypeFactory tf = TypeFactory.defaultInstance();
@@ -352,10 +341,7 @@ private int _countSupers(HierarchicType t)
352341
/* Unit tests: map/collection type parameter resolution
353342
/**********************************************************
354343
*/
355-
356-
/**
357-
* @since 1.6
358-
*/
344+
359345
public void testMapTypesSimple()
360346
{
361347
TypeFactory tf = TypeFactory.defaultInstance();
@@ -365,9 +351,6 @@ public void testMapTypesSimple()
365351
assertEquals(tf.constructType(Boolean.class), mapType.getContentType());
366352
}
367353

368-
/**
369-
* @since 1.6
370-
*/
371354
public void testMapTypesRaw()
372355
{
373356
TypeFactory tf = TypeFactory.defaultInstance();
@@ -377,9 +360,6 @@ public void testMapTypesRaw()
377360
assertEquals(tf.constructType(Object.class), mapType.getContentType());
378361
}
379362

380-
/**
381-
* @since 1.6
382-
*/
383363
public void testMapTypesAdvanced()
384364
{
385365
TypeFactory tf = TypeFactory.defaultInstance();
@@ -402,8 +382,6 @@ public void testMapTypesAdvanced()
402382
/**
403383
* Specific test to verify that complicate name mangling schemes
404384
* do not fool type resolver
405-
*
406-
* @since 1.6
407385
*/
408386
public void testMapTypesSneaky()
409387
{
@@ -416,8 +394,6 @@ public void testMapTypesSneaky()
416394

417395
/**
418396
* Plus sneaky types may be found via introspection as well.
419-
*
420-
* @since 1.7
421397
*/
422398
public void testSneakyFieldTypes() throws Exception
423399
{
@@ -438,8 +414,6 @@ public void testSneakyFieldTypes() throws Exception
438414

439415
/**
440416
* Looks like type handling actually differs for properties, too.
441-
*
442-
* @since 1.7
443417
*/
444418
public void testSneakyBeanProperties() throws Exception
445419
{
@@ -533,5 +507,16 @@ public void testMoreSpecificType()
533507
assertSame(t1, tf.moreSpecificType(t1, t2));
534508
assertSame(t2, tf.moreSpecificType(t2, t1));
535509
}
510+
511+
// [Issue#489]
512+
public void testCacheClearing()
513+
{
514+
TypeFactory tf = TypeFactory.defaultInstance().withModifier(null);
515+
assertEquals(0, tf._typeCache.size());
516+
tf.constructType(getClass());
517+
assertEquals(1, tf._typeCache.size());
518+
tf.clearCache();
519+
assertEquals(0, tf._typeCache.size());
520+
}
536521
}
537522

0 commit comments

Comments
 (0)