7580 Commits
Author SHA1 Message Date
cpovirk 89eb04b66e Bump Error Prone, and remove ReferenceEquality suppressions for Thread comparisons.
The suppressions are no longer necessary as of cl/937358981, which is [part of Error Prone 2.51.0](https://github.com/google/error-prone/commit/1259c50f8f164fb021dbdde08651602964ae6fd8).

RELNOTES=n/a
PiperOrigin-RevId: 1008358244
2026-10-27 14:02:13 -07:00
cpovirk c5e32cfaa9 Remove protected from test helpers, which are necessarily used only within the package.
Then, where appropriate, make them `private`, or even inline them.

(I guess that I've set aside my "Why even write '`private`' in a test class at all?" perspective, at least for the moment :))

RELNOTES=n/a
PiperOrigin-RevId: 1008110306
2026-10-27 08:09:24 -07:00
cpovirk 0229d325e6 Use MIN_POSITIVE_VALUE.
RELNOTES=n/a
PiperOrigin-RevId: 1008090972
2026-10-27 07:39:47 -07:00
cpovirk 9d36284ff4 Use @GuardedBy more.
(prompted by cl/1002439657)

RELNOTES=n/a
PiperOrigin-RevId: 1008086513
2026-10-27 07:32:38 -07:00
cpovirk 0b93bfbf68 Introduce and use a package-private SimpleForwardingCollection.
(prompted by a review comment in https://github.com/google/guava/commit/37535d73f0416f30e0301efe61a8eb8ede44c1b7)

We should easily make this available publicly, but we've had reservations around our `Forwarding*` classes in general (b/5231423), so I'm reluctant to expose more there without further thought.

RELNOTES=n/a
PiperOrigin-RevId: 1008047203
2026-10-27 06:17:03 -07:00
Tanishq Choudhary 37535d73f0 Check the predicate on setValue calls from filtered Multimap entries.
Compare https://github.com/google/guava/commit/b157643c41f9ee6a38732b4fa1a590ba187912d9.

Fixes https://github.com/google/guava/pull/8781
Fixes https://github.com/google/guava/pull/8785

RELNOTES=n/a
PiperOrigin-RevId: 1007326886
2026-10-26 09:14:36 -07:00
huang 5ae56d77e6 Make rotate a no-op on an empty range.
`rotate(array, distance, fromIndex, toIndex)` computed `length` and `-distance % length` without guarding an empty range, so a call with `fromIndex == toIndex` threw `ArithmeticException`. Return early when the range has fewer than two elements.

Fixes https://github.com/google/guava/pull/8772
Fixes https://github.com/google/guava/pull/8774

RELNOTES=`primitives`: Fixed `ArithmeticException` when calling `rotate` on an empty subrange of a multi-element array.
PiperOrigin-RevId: 1006325060
2026-10-24 09:23:31 -07:00
cpovirk 1b1d120f9c Improve testing of ForwardingMultiset.StandardElementSet:
- More clearly document that `StandardElementSet` is the class that we're testing _and_ where the list of legal methods is documented.
- Make methods throw by default (by virtue of calling `delegate()`), tightening the restrictions on which methods can be called.

(further evidence for https://github.com/google/guava/issues/1575)

RELNOTES=n/a
PiperOrigin-RevId: 1005714075
2026-10-23 10:51:29 -07:00
cpovirk d6e1fd3840 Document more JDK alternatives to Guava methods.
RELNOTES=n/a
PiperOrigin-RevId: 1005640167
2026-10-23 09:03:20 -07:00
cpovirk 7caa334327 Make some methods static.
...by using http://errorprone.info/bugpattern/MethodCanBeStatic.

RELNOTES=n/a
PiperOrigin-RevId: 1005209034
2026-10-22 18:34:06 -07:00
cpovirk d194bb3b0a Improve skipFully docs:
- Recommend `InputStream.skipNBytes` where available.
- Document behavior for negative requested skip values. The behavior matches that of [`InputStream.skipNBytes`](https://docs.oracle.com/en/java/javase/27/docs/api/java.base/java/io/InputStream.html#skipNBytes(long)) in practice, even though the contract of `skipNBytes` leaves open the possibility of different behavior in subclasses.

(relevant to https://github.com/google/guava/pull/8760, where it was suggested by arshsmith1)

RELNOTES=n/a
PiperOrigin-RevId: 1004997792
2026-10-22 13:10:57 -07:00
cpovirk ad73fbb9be Fix behavior of replaceAll in AbstractBiMap and HashBiMap when the given function throws.
Currently:

- `AbstractBiMap` runs `replaceAll` on its forward map first, so if that throws in the middle, its inverse is never updated. (Additionally, if it detects a value conflict while populating the inverse later, it likewise ends up in an inconsistent state.)

- `HashBiMap` clears itself at the beginning, so if it throws in the middle, it ends up missing entries.

Fixes https://github.com/google/guava/pull/8766 (by arshsmith), which proposed a fix for the specific case of `filterValues`.

RELNOTES=n/a
PiperOrigin-RevId: 1004886559
2026-10-22 10:42:01 -07:00
Chaoren Lin 2a18700ca0 Document that MediaType parameter values disallow ASCII control characters other than \t.
[Commit 5e82f2f](https://github.com/google/guava/commit/5e82f2f528fbbd970e00748025b48e3eb42ed702) restricted parameter values to printable ASCII and `\t` (matching [RFC 9110 Section 5.6.4](https://datatracker.ietf.org/doc/html/rfc9110#section-5.6.4)), whereas the class Javadoc still stated without qualification that all values follow RFCs 2045 and 2046.

RELNOTES=n/a
PiperOrigin-RevId: 1004800398
2026-10-22 08:38:15 -07:00
cpovirk b157643c41 Check the predicate on new values in filtered BiMap.replaceAll.
This change is prompted by https://github.com/google/guava/pull/8766 by arshsmith1. It is not a fix for _all_ the problems in this area, just incremental progress.

(The tests here touch on [the lack of a `ForwardingBiMap`](https://github.com/google/guava/issues/3906). But given the recent [additional evidence](https://github.com/google/guava/pull/8758) of [the dangers of forwarding collections](https://github.com/google/guava/issues/1575), I'm not in any rush to add one.)

RELNOTES=n/a
PiperOrigin-RevId: 1004410771
2026-10-21 19:24:01 -07:00
Lubaba Khalid 7b64964048 Treat leading, trailing, and consecutive $ in a class name as part of a top-level class name.
`ClassInfo.isTopLevel()` (and so `ClassPath.getTopLevelClasses()`) assumed that any `$` in a class name marks a nested class, so generated top-level classes like `$AutoValue_Foo` were silently dropped. `getSimpleName()` had the same problem, returning `AutoValue_Foo`.

_Consecutive_ `$` characters generally appear in runtime-generated classes, in which case they are outside the domain of `ClassPath`. However, they can appear at compile time, too, such as in desugared Android code—though, in the specific example of Android, `ClassPath` may well not work anyway. In any case, such classes don't represent true nested classes.

This new logic is all still based on heuristics, but it handles the common cases of generated class names.

Fixes https://github.com/google/guava/pull/8740
Fixes https://github.com/google/guava/issues/3349 well enough in practice.

RELNOTES=n/a
PiperOrigin-RevId: 1004273644
2026-10-21 15:22:57 -07:00
Colin Decker e641f0717a Change the streams returned by BaseEncoding's encodingStream and
`decodingStream` methods to synchronize their methods as typical of
`InputStream` and `OutputStream` implementations.

RELNOTES=n/a
PiperOrigin-RevId: 1004050756
2026-10-21 10:36:29 -07:00
Kurt Alfred Kluever adf5554e7e Add Doubles.MIN_POSITIVE_VALUE and Floats.MIN_POSITIVE_VALUE, aliases of the MIN_VALUE constants for those types.
`Double.MIN_VALUE` and `Float.MIN_VALUE` represent the smallest positive nonzero values (`2^-1074` and `2^-149`) rather than the most negative finite values, unlike `Integer.MIN_VALUE` and `Long.MIN_VALUE`.

RELNOTES=`primitives`: Added `Doubles.MIN_POSITIVE_VALUE` and `Floats.MIN_POSITIVE_VALUE` as more clearly named aliases for `Double.MIN_VALUE` and `Float.MIN_VALUE`.
PiperOrigin-RevId: 1004024484
2026-10-21 10:04:34 -07:00
Divyansh fa64cc7c2b Make BaseEncoding.encodingStream().close() idempotent.
Fixes https://github.com/google/guava/issues/5284
Fixes https://github.com/google/guava/pull/8642

RELNOTES=n/a
PiperOrigin-RevId: 1003397953
2026-10-20 14:31:51 -07:00
cpovirk fb2cb389a4 Make TODOs more stylish.
RELNOTES=n/a
PiperOrigin-RevId: 1003327482
2026-10-20 12:58:13 -07:00
cpovirk e07dfd2d8a Address a http://errorprone.info/bugpattern/Finally warning.
RELNOTES=n/a
PiperOrigin-RevId: 1003277753
2026-10-20 11:54:42 -07:00
arshiya tabasum de57a419b5 Check the predicate on setEntry calls from filterEntries(...).entrySet().toArray(...).
`FilteredEntryMap.EntrySet` wrapped only the entries returned by `iterator()`, so the entries returned by `toArray()` were the backing map's own entries, and their `setValue` bypassed the filter.

The fix is to override `toArray`. But instead of using `standardToArray` like `AbstractBiMap.EntrySet` and `UnmodifiableEntries` do, we use `newArrayList(iterator()).toArray(...)` like  `FilteredMapValues` and `FilteredEntryMap.KeySet` do so that we avoid evaluating the predicate against all elements twice (once in `size()` and once in `iterator()`).

- Fixes https://github.com/google/guava/pull/8758
- Support for https://github.com/google/guava/issues/1575

RELNOTES=n/a
PiperOrigin-RevId: 1003049749
2026-10-20 06:13:31 -07:00
Éamonn McManus 669a232b4e In ThreadFactoryBuilder, propagate null from newThread on the backing ThreadFactory.
`ThreadFactory.newThread` is permitted to return `null` to reject a request to create a thread. Previously, a factory built by `ThreadFactoryBuilder` threw `NullPointerException` if its backing factory returned `null`.

Fixes https://github.com/google/guava/issues/3568.
Closes https://github.com/google/guava/pull/8742.

RELNOTES=In the `ThreadFactory` returned by `ThreadFactoryBuilder`, a null return from `newThread` on the backing `ThreadFactory` is now propagated to the caller. Previously it triggered a NullPointerException.
PiperOrigin-RevId: 1001877586
2026-10-18 10:40:59 -07:00
cpovirk 665d66e83c Prepare for when our nullness checker knows that getFileAttributeView can return null.
RELNOTES=n/a
PiperOrigin-RevId: 1001870050
2026-10-18 10:09:50 -07:00
cpovirk 9247d70e16 Make FileBackedOutputStream even more resilient to broken temp-directory permissions than java.nio.file.Files.createTempFile is.
_If_ `java.io.tmpdir` is world-writable and does not set the very important sticky bit, then an attacker has a chance to unlink the temp file and replace it with a symlink between when it is created and when it is opened. This could cause the user of the stream to write/read data to/from an unintended location.

It's not clear that it's worth defending against this, given that the problem arises only with broken temp-directory permissions, which are much more likely to open holes elsewhere than here. But given the rise of security scanning over time, I'm figuring that it's worth addressing even _some_ borderline reports (like this one from our internal scans) when it appears straightfoward and safe enough to do so.

RELNOTES=n/a
PiperOrigin-RevId: 1001464603
2026-10-17 07:22:15 -07:00
arshiya tabasum 5e82f2f528 Reject control characters in MediaType parameter values.
Fixes https://github.com/google/guava/pull/8743

RELNOTES=n/a
PiperOrigin-RevId: 1000906952
2026-10-16 09:31:15 -07:00
Lubaba Khalid dea4984457 Document that SimpleStatsCounter.snapshot() may be
inconsistent with concurrent updates.

`SimpleStatsCounter` is documented as thread-safe, but it updates its counters independently
and without locking, so a snapshot taken during an update can include part of it (for example,
a load-success count without the corresponding load time). That's intentional for performance,
so document it rather than adding synchronization.

Fixes https://github.com/google/guava/pull/8741

RELNOTES=n/a
PiperOrigin-RevId: 999541957
2026-10-14 12:33:21 -07:00
cpovirk 2b86a82166 Keep the referent alive until after we've finished creating and registering the reference.
This prevents (for the case of `GcFinalization`, but other cases are similar):
- a `NullPointerException` if our finalization logic runs before `FinalizableReference` has assigned to `this.latch`
- indefinite retention of the `Reference` object if our finalization logic runs before `reference.add`

Fixes https://github.com/google/guava/issues/8738

RELNOTES=n/a
PiperOrigin-RevId: 998855369
2026-10-13 13:32:37 -07:00
arshiya tabasum 6b3a8d7498 Fix integer overflow in InetAddresses scope-ID parsing.
Fixes https://github.com/google/guava/pull/8735

RELNOTES=n/a
PiperOrigin-RevId: 996752850
2026-10-09 14:19:13 -07:00
cpovirk 1485e0093c Further tweak Javadoc output:
- While it makes sense to have an HTML `<title>` (i.e., what shows up in the tab button or taskbar button for that page) that says (e.g.) "Truth API," it's weirder for the in-page title to say "Truth API" instead of just "Truth." Javadoc lets us set the two independently; I just chose poorly in https://github.com/google/guava/commit/49300093df01df7d7bea5f1d657ecf58fbc4f596.
- Truth was showing a copyright date of 1980, presumably some kind of default from somewhere or other. I've given it [the same value as Guava](https://github.com/google/guava/blob/1da08c4d381abf3613ad956d3aec9fa77dfc94b2/pom.xml#L100).

It's possible that [JSpecify](https://github.com/jspecify/jspecify/issues/904) would have the same issue, though I'm not sure because it uses Gradle instead of Maven. But even if it does, I'm not sure that its Javadoc ends up with a summary page at the moment, I guess because it contains only one package? So maybe there's nowhere for "JSpecify API" to appear in the actual page text, only in the `<title>` where we want it.

RELNOTES=n/a
PiperOrigin-RevId: 996717116
2026-10-09 13:20:57 -07:00
TABISH AYUB RAZA 1da08c4d38 More frequently validate elements during TreeMultiset.setCount(element, oldCount, newCount).
But (for better or for worse) preserve the existing lenient behavior of `setCount(element, 0, 0)`.

Fixes https://github.com/google/guava/pull/8720

RELNOTES=n/a
PiperOrigin-RevId: 995897499
2026-10-08 09:48:57 -07:00
cpovirk 49300093df Hide our long "HEAD-SNAPSHOT" version numbers from the generated Javadoc.
Compare https://github.com/jspecify/jspecify/issues/904.

RELNOTES=n/a
PiperOrigin-RevId: 995344595
2026-10-07 14:11:46 -07:00
cpovirk 7573b12d80 Bump deps and plugins.
But don't update maven-surefire-plugin to 3.6.0: It appears to produce either module-system errors (under JDK 11) or infinite(?) loops over tests (under JDK 26).

- Fixes https://github.com/google/guava/pull/8726
- Fixes https://github.com/google/guava/pull/8725
- Fixes https://github.com/google/guava/pull/8724
- Fixes https://github.com/google/guava/pull/8723

RELNOTES=n/a
PiperOrigin-RevId: 995300021
2026-10-07 13:07:06 -07:00
cpovirk cbc66934d1 Belatedly update github.com docs for release 33.7.2.
RELNOTES=n/a
PiperOrigin-RevId: 995298973
2026-10-07 13:06:01 -07:00
cpovirk a24e79ef3e Fix more GWT/J2CL nullness annotations, and fix a GWT/J2CL nullness bug in cache.
RELNOTES=n/a
PiperOrigin-RevId: 995298922
2026-10-07 13:03:35 -07:00
cpovirk 99dfa90a13 Rework Dependabot config for Maven and Maven Wrapper.
The config from https://github.com/google/guava/commit/c05d28807a6f0fbcb0379349884632c07180a4bd is not working how I'd hoped: We're getting PRs to [bump deps like `org.codehaus.mojo:animal-sniffer-maven-plugin`](https://github.com/google/guava/pull/8725), not only PRs for Maven and Maven Wrapper. It's possible that we should just give in and accept those, too, but I was hoping to defer that.

I'm not confident that this new config will work, either!

RELNOTES=n/a
PiperOrigin-RevId: 995193422
2026-10-07 10:24:03 -07:00
dependabot[bot] 994a2fe5be Bump gradle/actions/setup-gradle
Bumps the github-actions group with 1 update: [gradle/actions/setup-gradle](https://github.com/gradle/actions).

Updates `gradle/actions/setup-gradle` from 6.3.0 to 6.4.0
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/9c971963bec38e04b3d30dcc455b5382be2fdbfb...3f5f9adaf7d9fecd50b5935e54106014257a94e6)

Fixes https://github.com/google/guava/pull/8727

RELNOTES=n/a
PiperOrigin-RevId: 995135938
2026-10-07 08:48:44 -07:00
cpovirk c05d28807a Request [automated updates to Maven and Maven Wrapper](https://github.com/dependabot/dependabot-core/pull/14812).
We still won't be able to approve these and have them automatically imported. But at least we'll get PRs that I can import manually, as I do currently for GitHub Actions.

RELNOTES=n/a
PiperOrigin-RevId: 995053987
2026-10-07 05:57:46 -07:00
cpovirk 3dab0e8773 Bump toolchain, Javadoc-generated links, and handwritten links to Java 27.
I rechecked links that looked worth rechecking.

RELNOTES=n/a
PiperOrigin-RevId: 994789692
2026-10-06 19:51:23 -07:00
Éamonn McManus 82786379da Recommend HashMap.newHashMap instead of Maps.newHashMapWithExpectedSize, etc.
Fixes https://github.com/google/guava/issues/8715.

RELNOTES=We now recommend `HashMap.newHashMap` instead of `Maps.newHashMapWithExpectedSize`, etc.
PiperOrigin-RevId: 994725599
2026-10-06 17:19:52 -07:00
cpovirk 90a2a9dda8 Remove bogus extends @Nullable Object from ConcurrentHashMap usage.
And document why we can't use `ConcurrentHashMap.newKeySet` here.

The bogus `extends @Nullable Object` isn't detected by our nullness checking because our J2CL builds don't use `@NullMarked` classes for `java.*`.

RELNOTES=n/a
PiperOrigin-RevId: 994652789
2026-10-06 15:09:15 -07:00
Mahammad Insaf 786bb1a9b4 Ignore negative skip counts in ByteStreams.limit streams.
`LimitedInputStream.skip` passed a negative count on to the delegate. `FileInputStream` then seeks backward and returns a negative value, which was subtracted from the bytes left, so the stream could move before the position where the limit began and supply more than the limit.

Fixes https://github.com/google/guava/pull/8712

RELNOTES=n/a
PiperOrigin-RevId: 994451753
2026-10-06 09:48:06 -07:00
cpovirk 52d12e4aa2 Bump Gradle to 9.8.0.
PiperOrigin-RevId: 993873679
2026-10-05 13:43:13 -07:00
cpovirk 81c7d030f8 Cap deserialized LocalCache+MapMakerInternalMap concurrency level at 1024.
1024 ought to be enough for anybody. And probably few people are serializing caches or weak-entry-based maps, anyway. And people should be using [Caffeine](https://github.com/ben-manes/caffeine).

There was already a cap of 64k, so these collections didn't permit arbitrary-sized allocations. Still, the reduction brings them more in line with what is already possible when deserializing built-in JDK types. See, for example, [`LogRecord`](https://github.com/openjdk/jdk/blob/4e8bec6f862b58732537dea15cb3dd50a01fede0/src/java.logging/share/classes/java/util/logging/LogRecord.java#L704) and [`ZoneRules`](https://github.com/openjdk/jdk/blob/4e8bec6f862b58732537dea15cb3dd50a01fede0/src/java.base/share/classes/java/time/zone/ZoneRules.java#L464) (though the constant factors are still different).

(If any user of the classes is directly passing a concurrency level of more than 1024, it's extremely likely that that user would be better off if we were to cap it to 1024 in that code path, too. But I'm not bothering in this CL.)

RELNOTES=n/a
PiperOrigin-RevId: 993749847
2026-10-05 09:58:26 -07:00
Kurt Alfred Kluever 51246d06bb Terminate bracketed hosts at the first closing bracket in HostAndPort.
RELNOTES=`net`: `HostAndPort.fromString` now rejects bracketed hosts that contain multiple closing brackets.
PiperOrigin-RevId: 993633306
2026-10-05 05:58:04 -07:00
cpovirk 74fb73b20e Hard-code the current JRE serialVersionUID values for classes whose serialization we test.
(This may mean a change for _Android_ values.)

We continue to [warn that not just `serialVersionUID` values but actual serialized forms can change over time](https://github.com/google/guava/blob/master/README.md#important-warnings). But it doesn't seem that occasional changes here are deterring users from persisting serialized forms _enough_ that those changes are net helpful to us: It's probably simplest to hard-code values to avoid issues like https://github.com/google/guava/issues/8693, and if we want to make a "real" change to the serialized form badly enough, then we still will.

Plus, we should probably specify `serialVersionUID` broadly to avoid any future problems computing it under Android or other environments that might not contain all the types used in [the class's relevant components](https://docs.oracle.com/en/java/javase/27/docs/specs/serialization/class.html#stream-unique-identifiers). (Compare https://github.com/google/guava/commit/230b0cdc69b03d5588cb72a38a10f51f64e2e223 and the similar changes that followed, as well as https://github.com/google/guava/commit/4d41665af1b05bad09039b82cb2a1a474a7bceaf.)

RELNOTES=n/a
PiperOrigin-RevId: 992670226
2026-10-02 19:59:00 -07:00
cpovirk 72dd370d95 Apply https://errorprone.info/bugpattern/AssertThrowsBlockToExpression suggestions.
RELNOTES=n/a
PiperOrigin-RevId: 992420855
2026-10-02 10:59:30 -07:00
dependabot[bot] 5dc4cd1ad4 Bump the github-actions group with 2 updates
Bumps the github-actions group with 2 updates: [actions/setup-java](https://github.com/actions/setup-java) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).

Updates `actions/setup-java` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/dd06d9cba3e5552c54d9f8ea23572deb30010f7c...de7274f081f381c8f8158605e0321c36c376e2e6)

Updates `github/codeql-action/upload-sarif` from 4.37.8 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Fixes https://github.com/google/guava/pull/8705

RELNOTES=n/a
PiperOrigin-RevId: 991768158
2026-10-01 10:41:16 -07:00
Kurt Alfred Kluever d860752657 Fix integer overflow in BaseEncoding.decodingStream for >2B characters
RELNOTES=n/a
PiperOrigin-RevId: 990549481
2026-09-29 14:59:05 -07:00
cpovirk b931fe9d6d Avoid eagerly allocating as much memory as a serialization payload requests.
See [the security advisory that this addresses](https://github.com/google/guava/security/advisories/GHSA-xxph-c9ww-hj94) (soon to be published as [CVE-2026-102554](https://nvd.nist.gov/vuln/detail/cve-2026-102554)). We will publish a release 33.7.2 with the fix.

RELNOTES=`collect`: Changed `MapMaker`, `CompactHashMap`, and `CompactHashSet` deserialization to [avoid eagerly allocating as much memory as a serialization payload requests](https://github.com/google/guava/security/advisories/GHSA-xxph-c9ww-hj94).
PiperOrigin-RevId: 990274733
2026-09-29 06:50:03 -07:00
cpovirk b0ab782522 Rewrite a few instances of if (!foo) { ... } else { ... }.
Yes, one of these is changing the "old implementation" in a benchmark. That could in theory affect performance, but it seems extremely unlikely to. And if somehow it does, it seems only fair to compare against this improved implementation, anyway. (My change makes that code look at lot like the code in `NewExecutionListWithoutReverse` and in the prod `ExecutionList` itself.)

RELNOTES=n/a
PiperOrigin-RevId: 989830275
2026-09-28 14:04:26 -07:00