It's because Guava does not ensure the eviction of the values automatically when the timeout value expires. It however does that during a series of read and write operations.
Per its documentation here:
Caches built with CacheBuilder do not perform cleanup and evict values "automatically," or instantly after a value expires, or anything of the sort. Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.
The reason for this is as follows: if we wanted to perform Cache maintenance continuously, we would need to create a thread, and its operations would be competing with user operations for shared locks. Additionally, some environments restrict the creation of threads, which would make CacheBuilder unusable in that environment.
To validate your onRemoval
on expiration, call cache#cleanUp
right before your 2nd read operation and it is supposed to call your onRemoval
.