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
| Feature | ConcurrentHashMap | Guava Cache |
|---|---|---|
| Lifecycle | Permanent storage, requires explicit remove | Supports automatic expiration and eviction |
| Eviction Mechanism | None | Capacity/time/reference eviction |
| Applicable Scenario | Long-term configuration information | High-frequency access temporary data |
LocalCache Core Structure
1. Segment-based Locking Design
- LocalCache internally maintains Segment array
- Controlled by
concurrencyLevelparameter (default 4) - Read operations are lock-free (volatile), write operations require Segment lock
2. Five Queue Mechanism
keyReferenceQueue: Tracks GC-recycled weak reference keysvalueReferenceQueue: Tracks GC-recycled weak/soft reference valuesrecencyQueue: Temporarily records recently accessed entrieswriteQueue: 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 accessexpireAfterWrite: 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:
- During get() operation: Check if the entry corresponding to the key has expired, remove if expired
- During put() operation: Check if cache size exceeds limit, trigger LRU eviction if so
Common Issue Troubleshooting
| Symptom | Root Cause | Fix |
|---|---|---|
| Memory continuously grows | Not set maximumSize | Configure maximumSize/maximumWeight |
| Low hit rate | Expiration time too short | Adjust expireAfterAccess/Write |
| Memory surges after no traffic | Lazy eviction not triggered | Periodically call cache.cleanUp() |
| Data loss caused by weak references | GC recycling too frequent | Use weak references only when memory pressured |