# Understanding Guava's Caching Mechanisms: CacheBuilder and LoadingCache Tutorial

> Explore Guava's caching mechanisms with CacheBuilder and LoadingCache. Learn automatic loading, eviction, expiration, and statistics to boost your application performance.

- Repository: [Google/guava](https://github.com/google/guava)
- Tags: tutorial
- Published: 2026-08-10

---

**Guava provides a flexible caching API centered around the `CacheBuilder`, `Cache`, and `LoadingCache` classes that support automatic loading, size-based eviction, time-based expiration, and detailed statistics collection.**

Google's Guava library offers sophisticated caching capabilities through its `com.google.common.cache` package, providing thread-safe, high-performance alternatives to manual map-based caching solutions. Understanding Guava's caching mechanisms enables developers to implement memory-efficient data layers with automatic eviction policies and loading strategies. This guide examines the core components and configuration options available in the `google/guava` repository.

## Core Components of Guava's Caching

The caching framework revolves around three primary abstractions that work together to provide both manual and automatic caching behaviors.

### CacheBuilder Configuration

Located in [`guava/src/com/google/common/cache/CacheBuilder.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/cache/CacheBuilder.java), the `CacheBuilder` class implements the fluent builder pattern for constructing customized cache instances. This class provides methods to configure **maximum size limits**, **expiration policies**, **reference types**, and **removal listeners** before instantiating the final cache object. The builder returns either a `LoadingCache` when supplied with a `CacheLoader` instance, or a manual `Cache` instance when built without a loader.

### Cache and LoadingCache Interfaces

The [`guava/src/com/google/common/cache/Cache.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/cache/Cache.java) file defines the base `Cache` interface, which provides fundamental operations including `getIfPresent()`, `put()`, `invalidate()`, and `asMap()`. For automatic value loading, [`guava/src/com/google/common/cache/LoadingCache.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/cache/LoadingCache.java) extends `Cache` to add the `get(K key)` method, which automatically invokes the cache loader when a key is absent, and `getAll(Iterable<? extends K> keys)` for efficient bulk loading operations.

## Key Caching Capabilities

Guava's caching mechanisms support multiple eviction strategies and monitoring features that address different memory management and performance requirements.

### Size-Based and Weight-Based Eviction

Developers can enforce memory bounds using the `maximumSize(long maximumSize)` method in `CacheBuilder`, which triggers **LRU (Least Recently Used)** eviction when the cache exceeds the specified entry count. For scenarios where entries vary significantly in memory footprint, the `weigher()` method allows assigning custom weights to entries, working in conjunction with `maximumWeight()` to evict based on total weight rather than simple entry counts.

### Time-Based Expiration Policies

The framework provides two distinct expiration mechanisms through `CacheBuilder`: `expireAfterWrite(Duration duration)` removes entries a fixed period after creation or last update, while `expireAfterAccess(Duration duration)` evicts entries that haven't been read within the specified timeframe. These policies execute automatically during write and read operations, ensuring stale data does not persist beyond configured time limits.

### Reference-Based Eviction with Weak and Soft References

For memory-sensitive applications, `CacheBuilder` supports `weakKeys()`, `weakValues()`, and `softValues()` configurations that allow the garbage collector to reclaim cached entries. When enabled, the cache does not prevent GC collection of its keys or values, making this approach ideal for transient data that should not trigger `OutOfMemoryError` conditions. Note that soft references (`softValues()`) are generally preferred over weak references for values, as they resist collection longer under memory pressure.

### Removal Listeners and Statistics Collection

The `removalListener(RemovalListener<K, V> listener)` method registers callbacks that receive `RemovalNotification` objects whenever entries are evicted or manually removed, enabling audit trails or cleanup operations. Performance monitoring is available through `recordStats()`, which instruments the cache to collect hit rates, miss counts, load times, and eviction statistics accessible via the `CacheStats` class defined in [`guava/src/com/google/common/cache/CacheStats.java`](https://github.com/google/guava/blob/main/guava/src/com/google/common/cache/CacheStats.java).

### Automatic Refresh Capabilities

The `refreshAfterWrite(Duration duration)` method configures asynchronous reloading of stale entries without blocking read operations. When an entry exceeds the refresh duration, subsequent reads return the existing value while triggering the `CacheLoader` to fetch updated data in the background, ensuring low latency under load while maintaining data freshness.

## Practical Implementation Examples

The following examples demonstrate common configuration patterns using `CacheBuilder` and the associated interfaces.

### Basic Loading Cache with Size and Time Limits

This example from `guava/src/com/google/common/cache/` demonstrates a `LoadingCache` with automatic loading, size-based eviction, and expiration:

```java
// Manual cache with size limit and expiration
LoadingCache<String, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(10_000)                     // size-based eviction
    .expireAfterWrite(Duration.ofMinutes(10)) // time-based eviction
    .removalListener((RemovalNotification<String, Graph> n) ->
        System.out.println("Removed: " + n.getKey() + " because " + n.getCause()))
    .recordStats()                            // enable statistics
    .build(new CacheLoader<String, Graph>() {
      @Override public Graph load(String key) throws Exception {
        return createExpensiveGraph(key);
      }
    });

```

### Cache with Weak References and Custom Ticker

For testing or specialized timing requirements, you can configure weak references and custom time sources:

```java
// Cache with weak keys and a custom ticker (useful for testing)
Ticker fakeTicker = Ticker.systemTicker(); // replace with a mock for tests
Cache<String, String> cache = CacheBuilder.newBuilder()
    .weakKeys()                      // keys are weakly referenced
    .ticker(fakeTicker)              // custom time source
    .build();

cache.put("foo", "bar");
System.out.println(cache.getIfPresent("foo")); // prints "bar"

```

## Summary

- **Guava's caching mechanisms** are implemented through `CacheBuilder`, `Cache`, and `LoadingCache` classes located in `guava/src/com/google/common/cache/`.
- **Automatic loading** is provided by implementing the `CacheLoader` abstract class and building a `LoadingCache` via `CacheBuilder.build(loader)`.
- **Eviction policies** include size-based (`maximumSize`), weight-based (`maximumWeight` with `weigher`), time-based (`expireAfterWrite`, `expireAfterAccess`), and reference-based (`weakKeys`, `softValues`) strategies.
- **Monitoring capabilities** include removal listeners for eviction callbacks and statistics collection via `recordStats()` to obtain `CacheStats` metrics.
- **Refresh functionality** allows non-blocking background updates using `refreshAfterWrite()` to maintain low latency while updating stale entries.

## Frequently Asked Questions

### What is the difference between Cache and LoadingCache in Guava?

`Cache` provides manual cache operations requiring explicit `put()` calls to populate entries, while `LoadingCache` automatically computes values using the `CacheLoader` specified during construction. When calling `get(key)` on a `LoadingCache`, the loader's `load()` method executes automatically if the key is absent, whereas `Cache` requires manual handling of missing entries or use of `get(key, Callable)`.

### How does Guava handle cache eviction when maximum size is reached?

When `maximumSize()` is configured and the cache exceeds the limit, Guava evicts the least recently used (LRU) entries until the size falls below the threshold. This eviction occurs during write operations and does not require a background thread, making it suitable for high-throughput environments without additional threading overhead.

### Can I use weak or soft references in Guava caches?

Yes, `CacheBuilder` supports `weakKeys()`, `weakValues()`, and `softValues()` configurations that allow the garbage collector to reclaim cached entries when memory pressure occurs. Weak references are collected aggressively during GC cycles, while soft references persist longer and are typically collected only before `OutOfMemoryError` conditions, making them preferable for value caching.

### How do I monitor cache performance in Guava?

Enable statistics collection by calling `recordStats()` during `CacheBuilder` configuration, then access metrics through `Cache.stats()`, which returns a `CacheStats` object. This object provides hit count, miss count, load success and exception counts, total load time, and eviction count, allowing precise measurement of cache efficiency and performance characteristics.