-
Notifications
You must be signed in to change notification settings - Fork 11k
Migrate off Unsafe (guava-jre) #6806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Can you provide some information about what problem you're seeing? We have included fallback implementations for cases in which |
Hi @cpovirk Yes we are using a static analyzer to see what are the packages that java 17 doesn't like to expose usage of CLASS sun.misc.Unsafe and it is identifying class sun.misc.Unsafe is a jdk internal class. package sun.misc is jdk internal after jdk 8. In jdk16, --illegal-access=deny was default. This option is ignored in jdk 17. usage context: sun.misc.Unsafe.getUnsafe call |
Is there something that we can put on our code to suppress the static analyzer for the classes that have a fallback implementation? If we can do that without adding any dependencies, then we'd probably do it. We probably should look at |
On the The ViewCVS frontend for the jsr166 repo has been offline for a while now, I believe. But the command-line instructions still work. The repo includes a copy of Or perhaps we just want to use |
JDK 24-ea+26 or later now issues this warning by default (see MNG-8399 for all of them):
For now, it can be suppressed using |
Thanks. Our current JDK@head project is |
We have an existing benchmark (in Caliper, sadly, rather than JMH) for single-threaded use of The only immediate takeaway from that is that we can't just flip our default to the |
Another thing for us to remember is that the way we try to initialize the various helpers with |
Initial benchmarks for |
AtomicReferenceFieldUpdater became much faster in OpenJDK's lead up to VarHandles, whereas in Java 5 it was slow due to reflection and allocations at every invocation, iirc. If that helps here is Shiplev's discussion on it using JHM: |
(followup cl/705490132) The method requires JDK 9+ to build, but our Maven build [always builds with JDK 23](#6549 (comment)). It also requires JDK 9+ to _run_, so I've added code to skip running the test under older versions. Much of my goal here is to shake out any ways that we might cause problems if we begin conditionally using Java 9+ APIs more widely, such as [for `VarHandle`](#6806 (comment)). RELNOTES=n/a PiperOrigin-RevId: 705498400
(followup cl/705490132) The method requires JDK 9+ to build, but our Maven build [always builds with JDK 23](#6549 (comment)). It also requires JDK 9+ to _run_, so I've added code to skip running the test under older versions. Much of my goal here is to shake out any ways that we might cause problems if we begin conditionally using Java 9+ APIs more widely, such as [for `VarHandle`](#6806 (comment)). RELNOTES=n/a PiperOrigin-RevId: 705498400
(followup cl/705490132) The method requires JDK 9+ to build, but our Maven build [always builds with JDK 23](#6549 (comment)). It also requires JDK 9+ to _run_, so I've added code to skip running the test under older versions. Much of my goal here is to shake out any ways that we might cause problems if we begin conditionally using Java 9+ APIs more widely, such as [for `VarHandle`](#6806 (comment)). RELNOTES=n/a PiperOrigin-RevId: 705498400
(followup cl/705490132) The method requires JDK 9+ to build, but our Maven build [always builds with JDK 23](#6549 (comment)). It also requires JDK 9+ to _run_, so I've added code to skip running the test under older versions. Much of my goal here is to shake out any ways that we might cause problems if we begin conditionally using Java 9+ APIs more widely, such as [for `VarHandle`](#6806 (comment)). RELNOTES=n/a PiperOrigin-RevId: 705512728
See #6806 (comment). Changes: - "`SafeAtomicHelper`" is arguably already too generic a name for that class, given that we have a `SynchronizedAtomicHelper` that also avoids using `Unsafe`. It's going to become even more overly generic (and more overly scary) when we likely introduce a `VarHandle`-based alternative. (And maybe we'll even remove the `Unsafe`-based one entirely?) Rename it. - Remove Javadoc from implementation classes, since it merely duplicates that from the superclass. - Fix links in the (package-private) Javadoc. I considered also renaming the `AtomicHelper` methods to match the terminology of `VarHandle`. This would mean only renaming `putThread`+`putNext` to... `setReleaseThread`? `setThreadReleasedly`? `setThreadUsingReleaseAccessMode`? I didn't find anything that I particularly liked. RELNOTES=n/a PiperOrigin-RevId: 705587524
See #6806 (comment). Changes: - "`SafeAtomicHelper`" is arguably already too generic a name for that class, given that we have a `SynchronizedAtomicHelper` that also avoids using `Unsafe`. It's going to become even more overly generic (and more overly scary) when we likely introduce a `VarHandle`-based alternative. (And maybe we'll even remove the `Unsafe`-based one entirely?) Rename it. - Remove Javadoc from implementation classes, since it merely duplicates that from the superclass. - Fix links in the (package-private) Javadoc. I considered also renaming the `AtomicHelper` methods to match the terminology of `VarHandle`. This would mean only renaming `putThread`+`putNext` to... `setReleaseThread`? `setThreadReleasedly`? `setThreadUsingReleaseAccessMode`? I didn't find anything that I particularly liked. RELNOTES=n/a PiperOrigin-RevId: 705868797
For now, this is only for the JRE flavor, not for Android. Our not entirely great benchmarks suggest that this may actually improve performance slightly over the current `Unsafe`-based implementation. This matches my sense that [alternatives to `Unsafe` have gotten faster](#6806 (comment)). There are plenty of other [places in Guava that we use `Unsafe`](#6806), but this is a start. Also: I'm going to consider this CL to "fix" #6549, even though: - We already started requiring newer versions of Java to build our _tests_ in cl/705512728. (This CL is the first to require a newer JDK to build _prod_ code, again only to _build_ it, not to _run_ it.) - This CL requires only Java 9, not Java 11. - None of the changes so far should require people who _build our Maven project_ to do anything, since our build automatically downloads a new JDK to use for javac since cl/655647768. RELNOTES=n/a PiperOrigin-RevId: 702770479
…possible. RELNOTES=Changed various classes to stop using `sun.misc.Unsafe` under Java 9+. PiperOrigin-RevId: 714943678
…possible. RELNOTES=Changed various classes to stop using `sun.misc.Unsafe` under Java 9+. PiperOrigin-RevId: 714943678
…possible. RELNOTES=Changed various classes to stop using `sun.misc.Unsafe` under Java 9+. PiperOrigin-RevId: 714943678
… endianness for reads. I noticed this during work to [avoid using `Unsafe`](#6806) (though it applies even if we do use `Unsafe`, as you'd guess from the `BIG_ENDIAN` check there). RELNOTES=n/a PiperOrigin-RevId: 714958103
… endianness for reads. I noticed this during work to [avoid using `Unsafe`](#6806) (though it applies even if we do use `Unsafe`, as you'd guess from the `BIG_ENDIAN` check there). RELNOTES=n/a PiperOrigin-RevId: 715368993
I'll need to publish a release with the recent changes here, but with that release, I'll consider this to be fixed: When running under Java 9+, I assume that someday we'll have to make further changes, perhaps to remove |
It's possible that we'll want to do something in the Android flavor for users who use it under newer JVMs: Currently, the code would still try to use We of course recommend using the JRE flavor when running under a JVM. But it can be easy for the Android flavor to sneak in through cross-platform libraries that use it as a dependency. I don't expect it to be especially common, but it will come up. This might actually be a case for a multi-release jar. But we'd want to see how that would affect Android users. (And I would expect to still find the occasional tool that doesn't understand multi-release jars, perhaps especially in the Android ecosystem, where they are presumably less used.) It's possible that the simpler course of action would be to perform a runtime version check. (We could also catch the exception that |
My mistake: It does fall back successfully. I had been confused with a separate problem, in which an internal utility was trying to preinitialize essentially all the classes in Guava, including |
Well... :) OK, it's still worth noting that, if you use |
...or maybe including the |
(This is still solved for Actually, I've been focused mostly on Hmm, I'd run some kind of test of what happens when fallback is off, but maybe I'd ignored the failures in the backport? Or, more likely, they got lost among some other failures from other tools that we use. I do see at least one failure related to Anyway, I will still come back to the |
Is there a way to track -android Unsafe usage migration? (Considering this issue is in closed state.) |
Thanks, I should really have filed a new issue. I've now done that: #7742 |
…n run under the JVM. Under Android, I still don't have us even _try_ `VarHandle`: - I'm not sure that using `VarHandle` is possible with our current internal Android build setup, as discussed in the internal commentary on cl/711733182. - Using `VarHandle` there may at least somewhat more complex: My testing suggests that some versions of Android expose `VarHandle` to our reflective check but don't actually expose `MethodHandles.Lookup.findVarHandle`. Accordingly, sgjesse@ [recommends using a check on `SDK_INT`](https://issuetracker.google.com/issues/134377851#comment4) ([33](https://developer.android.com/reference/java/lang/invoke/MethodHandles.Lookup#findVarHandle(java.lang.Class%3C?%3E,%20java.lang.String,%20java.lang.Class%3C?%3E)) or higher) instead of reflection under Android. Since `guava-android` can be used under the JVM, too, we'd need to use a combination of the SDK check _and_ reflection. And we'd need to perform the `SDK_INT` check reflectively, as [we do in `TempFileCreator`](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava/src/com/google/common/io/TempFileCreator.java#L75) (which, hmm, I should clean up as obsolete one of these days...). (We could at least _reduce_ the amount of reflection we need if we were to depend on the Android SDK at build time, as discussed in b/403282918.) - I have no idea whether `VarHandle` is faster or slower than `Unsafe` there (and I can't easily tell because of the build problems above). - I'm not aware of efforts to remove `Unsafe` under Android. This CL has two advantages for JVM users of `guava-android`: - It eliminates a warning about usage of `Unsafe` under newer JDKs. Note that `AbstractFuture` _already_ has run correctly if access to `Unsafe` is outright disallowed (as with `-sun-misc-unsafe-memory-access=deny`): It detects this and falls back to an alternative implementation. However, if `Unsafe` is available but produces warnings, `guava-android` would use it, triggering those warnings. This CL makes Guava not even try to use it under newer JVMs because it now tries `VarHandle` first. - `VarHandle` may be marginally faster than `Unsafe` under the JVM, as discussed in cl/711733182. (It also doesn't lead to VM crashes if you manage to pass `null` where you shouldn't, as I did back in b/397641020 :) But that's more something that's nice for us as Guava developers, not something that's nice for Guava _users_.) This CL is probably the most _prominent_ part of [our migration of `guava-android` off `Unsafe`](#7742). It is debatable whether it is the most _important_, given that [at least one class, `Striped64`, does not seem to have a fallback at all if `Unsafe` is unavailable](#6806 (comment)). Still, this CL addresses the warning that most users are seeing, and it gives us some precedent for how to deal with `Striped64`. Finally, it looks like our existing tests for `VarHandle` had [a mismatch between the context class loader and the class loader that we load `AbstractFutureTest` in](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java#L105-L107)? That seems fairly bad. This CL fixes it, extracting a method to guard against future such mismatches. Out of an abundance of caution, I made a similar change in `AggregateFutureStateFallbackAtomicHelperTest`, even though there's not really an opportunity for a mismatch there, given that there's only one alternative class loader. RELNOTES=`util.concurrent`: Changed the `guava-android` copy of `AbstractFuture` to try `VarHandle` before `Unsafe`, eliminating a warning under newer JDKs. PiperOrigin-RevId: 741611120
…n run under the JVM. Under Android, I still don't have us even _try_ `VarHandle`: - I'm not sure that using `VarHandle` is possible with our current internal Android build setup, as discussed in the internal commentary on cl/711733182. - Using `VarHandle` there may at least somewhat more complex: My testing suggests that some versions of Android expose `VarHandle` to our reflective check but don't actually expose `MethodHandles.Lookup.findVarHandle`. Accordingly, sgjesse@ [recommends using a check on `SDK_INT`](https://issuetracker.google.com/issues/134377851#comment4) ([33](https://developer.android.com/reference/java/lang/invoke/MethodHandles.Lookup#findVarHandle(java.lang.Class%3C?%3E,%20java.lang.String,%20java.lang.Class%3C?%3E)) or higher) instead of reflection under Android. Since `guava-android` can be used under the JVM, too, we'd need to use a combination of the SDK check _and_ reflection. And we'd need to perform the `SDK_INT` check reflectively, as [we do in `TempFileCreator`](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava/src/com/google/common/io/TempFileCreator.java#L75) (which, hmm, I should clean up as obsolete one of these days...). (We could at least _reduce_ the amount of reflection we need if we were to depend on the Android SDK at build time, as discussed in b/403282918.) - I have no idea whether `VarHandle` is faster or slower than `Unsafe` there (and I can't easily tell because of the build problems above). - I'm not aware of efforts to remove `Unsafe` under Android. This CL has two advantages for JVM users of `guava-android`: - It eliminates a warning about usage of `Unsafe` under newer JDKs. Note that `AbstractFuture` _already_ has run correctly if access to `Unsafe` is outright disallowed (as with `-sun-misc-unsafe-memory-access=deny`): It detects this and falls back to an alternative implementation. However, if `Unsafe` is available but produces warnings, `guava-android` would use it, triggering those warnings. This CL makes Guava not even try to use it under newer JVMs because it now tries `VarHandle` first. - `VarHandle` may be marginally faster than `Unsafe` under the JVM, as discussed in cl/711733182. (It also doesn't lead to VM crashes if you manage to pass `null` where you shouldn't, as I did back in b/397641020 :) But that's more something that's nice for us as Guava developers, not something that's nice for Guava _users_.) This CL is probably the most _prominent_ part of [our migration of `guava-android` off `Unsafe`](#7742). It is debatable whether it is the most _important_, given that [at least one class, `Striped64`, does not seem to have a fallback at all if `Unsafe` is unavailable](#6806 (comment)). Still, this CL addresses the warning that most users are seeing, and it gives us some precedent for how to deal with `Striped64`. Finally, it looks like our existing tests for `VarHandle` had [a mismatch between the context class loader and the class loader that we load `AbstractFutureTest` in](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java#L105-L107)? That seems fairly bad. This CL fixes it, extracting a method to guard against future such mismatches. Out of an abundance of caution, I made a similar change in `AggregateFutureStateFallbackAtomicHelperTest`, even though there's not really an opportunity for a mismatch there, given that there's only one alternative class loader. RELNOTES=`util.concurrent`: Changed the `guava-android` copy of `AbstractFuture` to try `VarHandle` before `Unsafe`, eliminating a warning under newer JDKs. PiperOrigin-RevId: 741611120
…n run under the JVM. Under Android, I still don't have us even _try_ `VarHandle`: - I'm not sure that using `VarHandle` is possible with our current internal Android build setup, as discussed in the internal commentary on cl/711733182. - Using `VarHandle` there may at least somewhat more complex: My testing suggests that some versions of Android expose `VarHandle` to our reflective check but don't actually expose `MethodHandles.Lookup.findVarHandle`. Accordingly, sgjesse@ [recommends using a check on `SDK_INT`](https://issuetracker.google.com/issues/134377851#comment4) ([33](https://developer.android.com/reference/java/lang/invoke/MethodHandles.Lookup#findVarHandle(java.lang.Class%3C?%3E,%20java.lang.String,%20java.lang.Class%3C?%3E)) or higher) instead of reflection under Android. Since `guava-android` can be used under the JVM, too, we'd need to use a combination of the SDK check _and_ reflection. And we'd need to perform the `SDK_INT` check reflectively, as [we do in `TempFileCreator`](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava/src/com/google/common/io/TempFileCreator.java#L75) (which, hmm, I should clean up as obsolete one of these days...). (We could at least _reduce_ the amount of reflection we need if we were to depend on the Android SDK at build time, as discussed in b/403282918.) - I have no idea whether `VarHandle` is faster or slower than `Unsafe` there (and I can't easily tell because of the build problems above). - I'm not aware of efforts to remove `Unsafe` under Android. This CL has two advantages for JVM users of `guava-android`: - It eliminates a warning about usage of `Unsafe` under newer JDKs. Note that `AbstractFuture` _already_ has run correctly if access to `Unsafe` is outright disallowed (as with `-sun-misc-unsafe-memory-access=deny`): It detects this and falls back to an alternative implementation. However, if `Unsafe` is available but produces warnings, `guava-android` would use it, triggering those warnings. This CL makes Guava not even try to use it under newer JVMs because it now tries `VarHandle` first. - `VarHandle` may be marginally faster than `Unsafe` under the JVM, as discussed in cl/711733182. (It also doesn't lead to VM crashes if you manage to pass `null` where you shouldn't, as I did back in b/397641020 :) But that's more something that's nice for us as Guava developers, not something that's nice for Guava _users_.) This CL is probably the most _prominent_ part of [our migration of `guava-android` off `Unsafe`](#7742). It is debatable whether it is the most _important_, given that [at least one class, `Striped64`, does not seem to have a fallback at all if `Unsafe` is unavailable](#6806 (comment)). Still, this CL addresses the warning that most users are seeing, and it gives us some precedent for how to deal with `Striped64`. Finally, it looks like our existing tests for `VarHandle` had [a mismatch between the context class loader and the class loader that we load `AbstractFutureTest` in](https://github.com/google/guava/blob/266ce0022a1c54244df1af0bde81116ed7703577/guava-tests/test/com/google/common/util/concurrent/AbstractFutureFallbackAtomicHelperTest.java#L105-L107)? That seems fairly bad. This CL fixes it, extracting a method to guard against future such mismatches. Out of an abundance of caution, I made a similar change in `AggregateFutureStateFallbackAtomicHelperTest`, even though there's not really an opportunity for a mismatch there, given that there's only one alternative class loader. RELNOTES=`util.concurrent`: Changed the `guava-android` copy of `AbstractFuture` to try `VarHandle` before `Unsafe`, eliminating a warning under newer JDKs. PiperOrigin-RevId: 743198569
The following classes are using sun.misc.Unsafe
com.google.common.cache.Striped64
com.google.common.hash.LittleEndianByteArray
com.google.common.primitives.UnsignedBytes
com.google.common.util.concurrent.AbstractFuture
class sun.misc.Unsafe is a jdk internal class. package sun.misc is jdk internal after jdk 8. In jdk16, --illegal-access=deny was default. This option is ignored in jdk 17. usage context: run method declaration (return type)
Refer http://openjdk.java.net/jeps/260
The text was updated successfully, but these errors were encountered: