# Guava Admin & Architecture Guide

This guide is for the engineers, architects, and toolchain owners who **integrate, govern, and
build** Guava — not just call it. It covers how the project is structured, how the two flavors are
produced, the binary-compatibility policy you depend on, security considerations, and the build and
release machinery. The companion **User Guide** covers day-to-day API usage.

> [!NOTE]
> Guava is a published Java library, not a deployable service. "Operations" here means managing
> Guava as a dependency in your systems — version policy, compatibility, classpath hygiene, build
> integration, and security review — plus, for contributors, building it from source.

---

## 1. Executive Summary

**Guava** (Google Core Libraries for Java) is an Apache-2.0-licensed library, in development since
2010, that supplies foundational Java building blocks: immutable and extended collection types
(multimap, multiset, bimap, table, ranges), a graph library, an in-memory cache, and utilities for
concurrency, I/O, hashing, math, primitives, strings, networking, reflection, and escaping. It is
used pervasively inside Google and broadly across the Java ecosystem.

| Attribute | Value |
|-----------|-------|
| Group ID | `com.google.guava` |
| Artifact ID | `guava` |
| Flavors | `-jre` (JDK 1.8+) and `-android` |
| Runtime dependency | `com.google.guava:failureaccess` (single) |
| License | Apache License 2.0 |
| Inception | 2010 |
| Build | Maven (multi-module), with a Gradle integration-test harness |
| Source layout | Main code under `guava/`; mirrored Android sources under `android/` |
| Javadoc | [guava.dev/api](https://guava.dev/api) |

> [!IMPORTANT]
> The single most important governance fact about Guava is its **compatibility contract**:
> non-`@Beta` APIs remain binary-compatible indefinitely. This is what makes Guava safe to place
> deep in a dependency graph — but it is conditioned on avoiding `@Beta` APIs (see §5).

---

## 2. Architecture

### 2.1 Repository structure

Guava is a Maven multi-module project. The main library is `guava/`; the `android/` tree is a
near-identical mirror maintained by an automated sync (contributors normally edit only the main
tree).

```
guava/                       (repository root, Maven parent: guava-parent)
├── guava/                   The JRE-flavor library  → artifact "guava"
│   └── src/com/google/common/
│       ├── base/            Preconditions, Optional, Strings, Splitter, CharMatcher, ...
│       ├── collect/         Immutable collections, Multimap, Multiset, Range, Ordering, ...
│       ├── cache/           CacheBuilder, LoadingCache, CacheLoader
│       ├── util/concurrent/ ListenableFuture, Futures, Service, RateLimiter, Monitor, ...
│       ├── hash/            Hashing, HashFunction, BloomFilter, Funnels
│       ├── io/              Files, MoreFiles, ByteSource/Sink, CharSource/Sink, BaseEncoding
│       ├── net/             InternetDomainName, InetAddresses, MediaType, HostAndPort
│       ├── primitives/      Ints, Longs, ... and immutable primitive arrays
│       ├── math/            IntMath, LongMath, BigIntegerMath, Stats, Quantiles
│       ├── reflect/         TypeToken, Invokable, ClassPath
│       ├── eventbus/        EventBus, AsyncEventBus, @Subscribe
│       ├── graph/           Graph, ValueGraph, Network, builders, Traverser, Graphs
│       ├── escape/, html/, xml/   Escaper framework and implementations
│       └── annotations/     @Beta, @VisibleForTesting, @GwtCompatible, ...
├── android/                 The Android-flavor mirror → artifact "guava" (-android version)
├── guava-bom/               Bill-of-materials POM for aligning versions
├── guava-testlib/           Reusable test suites for collection implementations
├── guava-tests/             The test suite and JMH-style benchmarks
├── guava-gwt/               GWT (Google Web Toolkit) super-source and bindings
├── futures/                 failureaccess (the one runtime dep) + listenablefuture shims
├── proguard/                ProGuard/R8 keep-rules shipped to consumers
├── integration-tests/       Gradle-based consumption tests
├── util/                    Maintainer shell scripts (snapshot deploy, doc update, reports)
└── pom.xml                  Parent POM (modules: guava, guava-bom, guava-gwt, testlib, tests)
```

### 2.2 Package map and relative size

The JRE source tree (`guava/src/com/google/common`) is dominated by the collections subsystem:

| Package | Source files | Role |
|---------|-------------:|------|
| `collect` | 216 | Immutable + extended collections; the largest subsystem |
| `util/concurrent` | 84 | Futures, services, executors, locks, rate limiting |
| `graph` | 54 | Graph/ValueGraph/Network model |
| `base` | 52 | Core utilities (preconditions, strings, functional types) |
| `io` | 38 | Source/sink I/O abstractions |
| `hash` | 34 | Hash functions and Bloom filters |
| `primitives` | 26 | Per-primitive utilities and immutable primitive arrays |
| `cache` | 22 | In-memory cache |
| `math` | 17 | Overflow/rounding-aware arithmetic, statistics |
| `reflect` | 17 | Generic-type reflection |
| `eventbus` | 12 | Publish/subscribe |
| `escape` | 11 | Escaper framework |
| `net` | 10 | Networking value types |
| `annotations` | 6 | Library annotations (`@Beta`, `@GwtCompatible`, ...) |
| `html`, `xml` | 3 each | Escaper implementations |

### 2.3 The two-flavor model

Guava ships two artifacts that share a group/artifact ID and differ only by version suffix:

```
                ┌──────────────────────────────────────────────┐
   guava/src ──►│ build (jvmEnvironment = standard-jvm)         │──► guava:NN.N.N-jre   (JDK 1.8+)
                └──────────────────────────────────────────────┘
   automated mirror ↓ (changes flow from guava/ into android/)
                ┌──────────────────────────────────────────────┐
 android/src ──►│ build (jvmEnvironment = android)             │──► guava:NN.N.N-android
                └──────────────────────────────────────────────┘
```

The parent POM encodes this with `variant.jvmEnvironment = standard-jvm` (and the corresponding
`android` variant), so a Gradle consumer's variant-aware resolution can request the right flavor.
The `android/` sources differ from `guava/` only where Android API-level constraints require it
(for example, avoiding Java 8+ APIs unavailable on older Android).

> [!CAUTION]
> Because both flavors publish as `com.google.guava:guava`, a dependency graph that pulls **both**
> variants will hit a Gradle variant-selection conflict (see Troubleshooting). Standardize on one
> flavor across the entire graph.

### 2.4 GWT support

`guava-gwt/` provides GWT "super-source" — alternative implementations of select classes that
compile to JavaScript — so a subset of Guava can run in the browser via Google Web Toolkit. This is
a niche consumer; most projects ignore it.

---

## 3. Requirements & Compatibility

| Concern | JRE flavor | Android flavor |
|---------|-----------|----------------|
| Minimum runtime | JDK 1.8+ | Android (tested to API level 23) |
| Build JDK | Java 11+ may be needed to *build*; output runs on Java 8 | same |
| Runtime dependency | `failureaccess:1.0.3` | `failureaccess:1.0.3` |
| Tested OS | Linux and Windows, across a range of OpenJDK versions | plus Android API 23 |

> [!WARNING]
> Some features, **especially in `com.google.common.io`**, are validated primarily on Linux and
> may not behave correctly on other platforms. Test platform-sensitive file operations on your
> actual target OS.

### 3.1 Annotation-only dependencies

Beyond the single runtime dependency, Guava declares several **annotation-only** dependencies
(used at compile time, not required at runtime), including JSpecify nullness annotations, Error
Prone annotations, and (historically) JSR-305. These do not add runtime weight; if your build flags
them as "used at runtime but declared as provided," that is expected.

---

## 4. Dependency Management

### 4.1 Aligning versions with the BOM

For multi-module builds, import the Guava BOM to keep every Guava-related artifact on the same
version:

```xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava-bom</artifactId>
      <version>33.6.0-jre</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
```

### 4.2 The `listenablefuture` shim

Guava historically published a standalone `listenablefuture` artifact so that libraries depending
only on `ListenableFuture` need not pull all of Guava. The current Guava ships an empty
`9999.0-empty-to-avoid-conflict-with-guava` version of that artifact whose sole purpose is to
**evict the older standalone copy** from the classpath, preventing duplicate-class conflicts. You
normally never reference it directly; it is managed transitively.

### 4.3 `failureaccess`

`com.google.guava:failureaccess` is the one artifact Guava needs at runtime. It exists so that
`AbstractFuture` can access failure state across module boundaries. Keep it on the classpath at the
version Guava resolves (currently `1.0.3`).

---

## 5. The Compatibility Contract (Critical Governance)

Guava's stability guarantees are the foundation of its safety as a deep dependency. Treat the
following as policy.

| Rule | Detail |
|------|--------|
| **Non-`@Beta` APIs are binary-compatible indefinitely** | They will not be removed. The last release to remove non-`@Beta` APIs was **Guava 21.0**. |
| **`@Deprecated` (non-`@Beta`) APIs are kept** | Deprecation is advisory, not a removal timer. |
| **`@Beta` APIs may change or vanish at any time** | No compatibility promise whatsoever. |
| **Serialized forms are unstable** | Do not persist Guava objects and expect a future version to read them, unless explicitly documented otherwise. |

> [!IMPORTANT]
> **If your code is itself a library** (used on classpaths you don't control), do **not** use
> `@Beta` APIs — a consumer pinned to a different Guava version could fail to link. Enforce this
> mechanically with the [Guava Beta Checker](https://github.com/google/guava-beta-checker), an
> Error Prone plugin that fails the build on `@Beta` usage.

> [!TIP]
> Application code (the top of the dependency graph, where you control the Guava version) may use
> `@Beta` APIs more freely, since you upgrade Guava and your own code together.

---

## 6. Security Analysis

Guava is a utility library with no network listeners, no privileged operations, and no
configuration of its own. Its security surface is the behavior of its APIs when fed hostile data.

| Area | Assessment |
|------|------------|
| Trust boundary | **Not designed to defend against a malicious caller.** Do not use Guava types as a boundary between trusted and untrusted code. |
| Deserialization | Serialized forms are version-unstable; deserializing attacker-controlled bytes is unsafe (see Bloom filter note below). |
| Weak hashes | `Hashing.md5()` and `Hashing.sha1()` are provided for legacy compatibility and are deprecated; they are cryptographically broken and must not be used for security. Prefer `sha256()` or stronger. |
| Escaping | `HtmlEscapers`/`XmlEscapers` ensure well-formedness, not full injection defense. Use a context-aware sanitizer for security-critical HTML. |
| Network parsing | `InternetDomainName`, `InetAddresses`, and `HostAndPort` parse untrusted strings safely (they validate and throw), but treat their *results* as untrusted input to downstream systems. |

> [!CAUTION]
> **`BloomFilter.readFrom(InputStream, Funnel)` and untrusted input** — the serialized format
> encodes the backing array size, so a hostile stream can declare an enormous `longArraySize` and
> drive an unbounded memory allocation (reported as issue #8463). Only deserialize Bloom filters you
> produced yourself, or validate size bounds before reading.

> [!NOTE]
> Guava follows [OpenSSF Best Practices](https://www.bestpractices.dev/projects/7197). Report
> suspected vulnerabilities through the project's standard channels rather than public issues.

### 6.1 ProGuard / R8 keep-rules

Guava ships consumer ProGuard configuration under `proguard/` so that shrinkers do not strip
classes that are loaded reflectively or referenced only by optional code paths. Shipped rule files:

| File | Protects |
|------|----------|
| `base.pro` | `base` reflective access (e.g. finalizable references, platform shims) |
| `collect.pro` | `collect` internals |
| `concurrent.pro` | `util.concurrent` (e.g. `AbstractFuture` atomic-helper selection) |
| `cache.pro` | `cache` internals |
| `hash.pro` | `hash` functions |
| `primitives.pro` | `primitives` |

> [!WARNING]
> If you use R8/ProGuard (typical on Android) and see `ClassNotFoundException`,
> `NoSuchMethodError`, or `AbstractFuture` falling back to a slower atomic helper at runtime,
> confirm Guava's bundled keep-rules are being applied. Stripping them is a common cause of
> shrink-related breakage.

---

## 7. Building From Source (Contributors)

### 7.1 Prerequisites

- A JDK (Java 11+ is recommended to **build**; the output remains Java 8-compatible).
- Maven — the repository includes the Maven Wrapper (`mvnw` / `mvnw.cmd`), so no separate Maven
  install is required.

### 7.2 Common commands

```bash
# Build and run the full test suite (from the repository root):
./mvnw install
```

```bash
# Build without tests:
./mvnw install -DskipTests
```

```bash
# Run a single test class:
./mvnw test -Dtest.include="**/SplitterTest.java"
```

```bash
# Choose the JDK that runs the tests (toolchain), independent of the build JDK:
./mvnw test -Dsurefire.toolchain.version=21
```

> [!NOTE]
> Tests run under the JDK named by `surefire.toolchain.version` (defaulting to the build JDK's
> `java.specification.version`). Some tests need reflective access to JDK internals and the build
> passes `--add-opens` for `java.base/java.lang`, `java.base/java.util`, and
> `java.base/sun.security.jca` automatically.

### 7.3 Module build order

The parent POM builds modules in this order: `guava` → `guava-bom` → `guava-gwt` →
`guava-testlib` → `guava-tests`. The `android/`, `futures/`, and `integration-tests/` trees build
through their own POMs.

### 7.4 Maintainer scripts (`util/`)

| Script | Purpose |
|--------|---------|
| `util/deploy_snapshot.sh` | Publish a `999.0.0-HEAD-*-SNAPSHOT` build from `master` |
| `util/update_snapshot_docs.sh` | Refresh the snapshot Javadoc/diffs on guava.dev |
| `util/gradle_integration_tests.sh` | Run the Gradle consumption tests under `integration-tests/` |
| `util/print_surefire_reports.sh` | Summarize Surefire test reports |

### 7.5 Contribution workflow

> [!IMPORTANT]
> Guava is a subset of Google's internal codebase, automatically synced to GitHub. **Pull requests
> are not merged directly into `master`.** Instead, maintainers apply the change internally; when it
> syncs out, the original author is credited on the commit.

Key contributor rules:

- [ ] **API changes require discussion first.** Open an issue with concrete use cases before
  writing code — API design and review come before implementation.
- [ ] **Significant changes need tests.** The project has strong coverage; mirror existing tests.
- [ ] **Sign the Google CLA** (individual or corporate) before contributing.
- [ ] **Apache-2.0 license header** on every file, copied from an existing file.
- [ ] **Format with the Google Java Style Guide.**
- [ ] **Do not edit `android/` directly** — a script mirrors changes from the main directories.

---

## 8. Operations: Managing Guava as a Dependency

Because Guava is a library, "operations" is dependency lifecycle management.

### 8.1 Upgrading

- [x] Track the [latest release](https://github.com/google/guava/releases/latest) and upgrade on a
  regular cadence; non-`@Beta` upgrades are binary-compatible, so bumps are usually low risk.
- [x] Read the snapshot **API diffs** ([guava.dev](https://guava.dev) → snapshot diffs) to see what
  changed between versions.
- [x] If you ship a library, keep the Beta Checker in CI so an upgrade never silently introduces a
  `@Beta` call.

### 8.2 Avoiding classpath conflicts

- [x] Pin a single flavor (`-jre` **or** `-android`) across the whole build.
- [x] Let the empty `listenablefuture:9999.0-empty-...` shim evict the old standalone artifact —
  don't exclude it.
- [x] Keep `failureaccess` on the runtime classpath at the version Guava resolves.

### 8.3 Monitoring & verification

- [x] Use `CacheBuilder.recordStats()` and read `Cache.stats()` (`hitRate`, `missCount`,
  `loadExceptionCount`) to observe cache effectiveness in production.
- [x] For `Service`/`ServiceManager`-based components, register a `ServiceManager.Listener` and
  expose `servicesByState()` and `startupDurations()` to your metrics.

---

## 9. Troubleshooting

### Error: Gradle `VariantSelectionByAttributesException` resolving Guava

**Cause:** The dependency graph requests both the `-jre` and `-android` variants of
`com.google.guava:guava`, and Gradle cannot reconcile the `jvmEnvironment` attribute (issue #8398).

**Resolution:**
1. Decide on one flavor for the whole project.
2. Force it: in Gradle, add a resolution strategy forcing `com.google.guava:guava:33.6.0-jre` (or
   the `-android` equivalent); in Maven, declare Guava explicitly in `dependencyManagement`.
3. Run a dependency report (`./gradlew dependencies` or `mvn dependency:tree`) to find which
   transitive dependency pulled the other flavor, and align it.

### Error: `NoSuchMethodError` / `ClassNotFoundException` after R8/ProGuard shrinking (Android)

**Cause:** The shrinker removed classes or members Guava loads reflectively because the bundled
keep-rules were not applied.

**Resolution:** Ensure the `proguard/*.pro` rules packaged with Guava are picked up by your build
(they are consumer rules and should apply automatically via the AAR/JAR metadata). Do not strip
them; add explicit `-keep` rules if your toolchain ignores bundled ones.

### Problem: `AbstractFuture` logs a fallback to a slower atomic helper

**Cause:** The optimal `sun.misc.Unsafe`/`AtomicReferenceFieldUpdater` path is unavailable —
commonly because a shrinker removed it or the runtime restricts reflective access.

**Resolution:** Apply `proguard/concurrent.pro`; on a module path, ensure required `--add-opens`
are present for tests/tools that need reflective access.

### Problem: Duplicate-class errors mentioning `ListenableFuture`

**Cause:** Both modern Guava and the old standalone `listenablefuture` artifact are on the
classpath.

**Resolution:** Let Guava's empty `listenablefuture` shim win (don't exclude it); run a dependency
tree to confirm only the `9999.0-empty-...` version is resolved.

### Problem: A build flags Guava's annotation dependencies as "used but undeclared"

**Cause:** JSpecify/Error Prone/JSR-305 annotations are compile-time only.

**Resolution:** This is expected; mark them as provided/optional or ignore the warning. They are not
needed at runtime.

---

## 10. Quick Reference

### 10.1 Coordinates

```xml
<!-- JRE -->
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>33.6.0-jre</version>
</dependency>
```

```gradle
implementation("com.google.guava:guava:33.6.0-jre")   // or -android
```

### 10.2 Key facts

| Fact | Value |
|------|-------|
| Group / artifact | `com.google.guava` / `guava` |
| Flavors | `-jre` (JDK 1.8+), `-android` |
| Runtime dependency | `failureaccess:1.0.3` (only) |
| License | Apache 2.0 |
| Compatibility | Non-`@Beta` APIs stable indefinitely; last removal in 21.0 |
| Beta enforcement | [Guava Beta Checker](https://github.com/google/guava-beta-checker) |
| BOM | `com.google.guava:guava-bom` |
| Javadoc | [guava.dev/api](https://guava.dev/api), `guava.dev/{ClassName}` |
| Build | `./mvnw install` (Maven Wrapper included) |

### 10.3 Subsystem owners' map

| If you need… | Look in package |
|--------------|-----------------|
| Argument checks, strings, functional types | `base` |
| Immutable / extended collections, ranges | `collect` |
| In-memory cache | `cache` |
| Futures, services, executors, rate limiting | `util.concurrent` |
| Hashing, Bloom filters | `hash` |
| File / stream / encoding I/O | `io` |
| Domain names, IPs, media types | `net` |
| Primitive utilities | `primitives` |
| Overflow-safe math, statistics | `math` |
| Generic-type reflection, classpath scanning | `reflect` |
| Publish/subscribe | `eventbus` |
| Graph / network modeling | `graph` |
| HTML/XML/URL escaping | `escape`, `html`, `xml`, `net` |

### 10.4 Governance checklist for adopting Guava

- [ ] Pick a flavor (`-jre`/`-android`) and pin it project-wide.
- [ ] Import `guava-bom` if you have multiple Guava artifacts.
- [ ] Add the Beta Checker if you ship a library.
- [ ] Apply Guava's ProGuard rules if you shrink (Android).
- [ ] Avoid deserializing Guava objects from untrusted input.
- [ ] Replace any `md5()`/`sha1()` security usage with `sha256()`+.
- [ ] Schedule periodic version upgrades; review API diffs each time.

---

_Generated June 2026 from google/guava at 9a5d60d. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
