TL;DR

  • Scenario: Guava Cache is widely used in production, but many lack understanding of LocalCache specific behavior
  • Conclusion: Guava achieves thread-safe local cache through LocalCache+Segment structure, reference queues, and access/write queues
  • Output: Core structure analysis + eviction mechanism explanation + common issue troubleshooting

Fundamental Differences: Guava Cache vs ConcurrentHashMap

FeatureConcurrentHashMapGuava Cache
LifecyclePermanent storage, requires explicit removeSupports automatic expiration and eviction
Eviction MechanismNoneCapacity/time/reference eviction
Applicable ScenarioLong-term configuration informationHigh-frequency access temporary data

LocalCache Core Structure

1. Segment-based Locking Design

  • LocalCache internally maintains Segment array
  • Controlled by concurrencyLevel parameter (default 4)
  • Read operations are lock-free (volatile), write operations require Segment lock

2. Five Queue Mechanism

  • keyReferenceQueue: Tracks GC-recycled weak reference keys
  • valueReferenceQueue: Tracks GC-recycled weak/soft reference values
  • recencyQueue: Temporarily records recently accessed entries
  • writeQueue: Ordered by write time (LRU)
  • accessQueue: Ordered by access time

3. Data Table Structure

AtomicReferenceArray<ReferenceEntry<K,V>> table: Hash table storage

ReferenceEntry contains: key, hash, valueReference, next fields

Eviction Mechanism

1. Capacity-based Eviction

Uses LRU (Least Recently Used) strategy for eviction

2. Timed Eviction

  • expireAfterAccess: Expires after access
  • expireAfterWrite: Expires after write

3. Reference-based Eviction

Supports weak reference keys, weak reference values, soft reference values

Lazy Eviction Mechanism

Guava Cache uses lazy eviction and does not actively scan the entire cache:

  1. During get() operation: Check if the entry corresponding to the key has expired, remove if expired
  2. During put() operation: Check if cache size exceeds limit, trigger LRU eviction if so

Common Issue Troubleshooting

SymptomRoot CauseFix
Memory continuously growsNot set maximumSizeConfigure maximumSize/maximumWeight
Low hit rateExpiration time too shortAdjust expireAfterAccess/Write
Memory surges after no trafficLazy eviction not triggeredPeriodically call cache.cleanUp()
Data loss caused by weak referencesGC recycling too frequentUse weak references only when memory pressured