Skip Headers

# Understanding the Internals of Soft and Hard Cache Weak Identity Map

Previous

Next

The `SoftCacheWeakIdentityMap` and `HardCacheWeakIdentityMap` types of identity map contain two caches:

- Reference cache: implemented as a `LinkedList` that contains soft or hard references, respectively

- Weak cache: implemented as a `HashMap` that contains weak references

When you create a `SoftCacheWeakIdentityMap` or `HardCacheWeakIdentityMap` with a specified size, the reference cache `LinkedList` is exactly this size. The weak cache `HashMap` is initialized to 100 percent of the specified size: the weak cache will grow when more objects than the specified size are read in. Because TopLink does not control garbage collection, the JVM can reap the weakly held objects whenever it sees fit.

Because the reference cache is implemented as a `LinkedList`, new objects are added to the end of the list. Because of this, it is by nature a least recently used (LRU) cache: fixed size, object at the top of the list is deleted, provided the maximum size has been reached.

The `SoftCacheWeakIdentityMap` and `HardCacheWeakIdentityMap` are essentially the same type of identity map. The `HardCacheWeakIdentityMap` was constructed to work around an issue with some JVMs.

If your application reaches a low system memory condition frequently enough, or if your platform's JVM treats weak and soft references the same, the objects in the reference cache may be garbage-collected so often that you will not benefit from the performance improvement provided by it. If this is the case, Oracle recommends that you use the `HardCacheWeakIdentityMap`. It is identical to the `SoftCacheWeakIdentityMap` except that it uses hard references in the reference cache. This guarantees that your application will benefit from the performance improvement provided by it.

When an object in a `HardCacheWeakIdentityMap` or `SoftCacheWeakIdentityMap` is pushed out of the reference cache, it gets put in the weak cache. Although it is still cached, TopLink cannot guarantee that it will be there for any length of time because the JVM can decide to garbage-collect weak references at anytime.

TopLink cleans up dead cache keys after every nth access to a `HardCacheWeakIdentityMap` or `SoftCacheWeakIdentityMap`. For example, if you set the size to 100, then TopLink locks the cache and cleans up these cache keys on the 100th access, 200th access, 300th access, and so on. Although this may appear to be a memory leak, it is not: it is a compromise that provides improved performance at the expense of holding on to memory until the nth access. While reducing n frees memory more frequently, it does so at the unacceptable performance cost of performing an enumeration of the cache too frequently.

If you are querying in memory and you absolutely need the guarantee that the objects are in memory, then you should have those classes set to `FullIdentityMap` (see "Full Identity Map"). Querying in memory with `SoftCacheWeakIdentityMap` or `HardCacheWeakIdentityMap` does not 100 percent guarantee that the query will retrieve the objects that you expect.

When you query in memory, TopLink does not move the objects around to maintain a strict LRU. This behavior occurs only when you merge or query the database. Not supporting in-memory LRU functionality is a compromise that enhances performance. To support in-memory LRU functionality, the identity map would have to be locked for the duration of the move, resulting in performance degradation.