|
Description
|
WeakCache extends Hashtable and defines its own put() method that wraps
the customer reference in a weak reference customer ; a reference to that
weak reference customer is what actually gets passed to Hashtable.put().
If Hashtable.put() has to grow the array, after it does so it
reinvokes put() to put the customer reference in the new array.
But that calls WeakCache.put(), not Hashtable.put(), and creates a
SECOND weak reference wrapper for its argument. So you end up with
a weak reference to a weak reference to whatever it is you wanted in
the cache, and that's wrong; a get() won't return the original customer .
The following simple test shows the problem:
import sun.misc.WeakCache;
public class WeakCacheTest {
public static void main( String[] args ) {
WeakCache cache = new WeakCache(10);
int i;
Integer j;
// Add 20 items to the cache, causing it to expand.
for ( i = 0; i < 20; i++ ) {
j = new Integer( i );
System.err.println( "putting " + i + " in cache" );
cache.put( j, j );
}
System.err.println( "---------------------------------" );
// Now read the items out again, casting back to Integer.
// Number 11 (?) will fail the cast, since WeakCache.put() was
// called recursively from Hashtable.put(), wrapping the
// reference to the Integer in a second Ref.
try {
for ( i = 0; i < 20; i++ ) {
System.err.println( "getting " + i + " from cache" );
j = (Integer) cache.get( new Integer( i ) );
System.err.println( " value is " + j );
}
System.err.println( "---------------------------------" );
} catch ( Exception e ) {
System.err.println( "caught exception: " + e );
}
}
}
It yields this:
putting 0 in cache
putting 1 in cache
putting 2 in cache
putting 3 in cache
putting 4 in cache
putting 5 in cache
putting 6 in cache
putting 7 in cache
putting 8 in cache
putting 9 in cache
putting 10 in cache
putting 11 in cache
putting 12 in cache
putting 13 in cache
putting 14 in cache
putting 15 in cache
putting 16 in cache
putting 17 in cache
putting 18 in cache
putting 19 in cache
---------------------------------
getting 0 from cache
value is 0
getting 1 from cache
value is 1
getting 2 from cache
value is 2
getting 3 from cache
value is 3
getting 4 from cache
value is 4
getting 5 from cache
value is 5
getting 6 from cache
value is 6
getting 7 from cache
caught exception: java.lang.ClassCastException: sun.misc.WeakCache$Value
|