JEP draft: Warn about use of Memory-Access Methods in `sun.misc.Unsafe`

AuthorRon Pressler & Alex Buckley
OwnerRon Pressler
TypeFeature
ScopeJDK
StatusSubmitted
Componentcore-libs
Discussionjdk dash dev at openjdk dot org
EffortS
DurationS
Relates toJEP 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for Removal
Reviewed byAlan Bateman
Created2024/10/14 17:42
Updated2024/10/29 15:38
Issue8342077

Summary

Issue a warning at run time if any memory-access method in sun.misc.Unsafe is called. All memory-access methods were terminally deprecated in JDK 23. We strongly encourage library developers to migrate from sun.misc.Unsafe to supported replacements, so that applications can migrate smoothly to modern JDK releases.

History

This JEP is the successor to JEP 471, which deprecated the memory-access methods in sun.misc.Unsafe for removal in a future release and described a gradual process of removal. The Goals, Non-Goals, Motivation, and Risks and Assumptions section of this JEP are essentially identical to that of JEP 471 but are reproduced here for the reader’s convenience.

Goals

Non-Goals

Motivation

The sun.misc.Unsafe class was introduced in 2002 as a way for Java classes in the JDK to perform low-level operations. Most of its methods — 79 out of 87 — are for accessing memory, either in the JVM's garbage-collected heap or in off-heap memory, which is not controlled by the JVM. As the name of the class suggests, these memory-access methods are unsafe: They can lead to undefined behavior, including JVM crashes. Therefore, they were not exposed as a standard API. They were neither envisaged for use by a broad range of clients nor intended to be permanent. Rather, they were introduced with the assumption that they were exclusively for use within the JDK, and that callers within the JDK would perform exhaustive safety checks before using them, and that safe standard APIs for this functionality would eventually be added to the Java Platform.

However, with no way in 2002 to prevent sun.misc.Unsafe from being used outside the JDK, its memory-access methods became a handy tool for library developers who wanted more power and performance than standard APIs could offer. For example, sun.misc.Unsafe::compareAndSwap can perform a CAS (compare-and-swap) operation on a field without the overhead of the java.util.concurrent.atomic API, while sun.misc.Unsafe::setMemory can manipulate off-heap memory without the 2GB limitation of java.nio.ByteBuffer. Libraries that do rely on ByteBuffer to manipulate off-heap memory, such as Apache Hadoop and Cassandra, use sun.misc.Unsafe::invokeCleaner to improve efficiency by deallocating off-heap memory promptly.

Unfortunately, not all libraries are diligent at performing safety checks before calling the memory-access methods, so there is a risk of failures and crashes in applications. Some uses of the methods are unnecessary, driven by the ease of copy-and-paste from online forums. Other uses of the methods may cause the JVM to disable optimizations, resulting in worse performance than if ordinary Java arrays had been used. Nevertheless, because use of the memory-access methods is so widespread, sun.misc.Unsafe was not encapsulated alongside other low-level APIs in JDK 9 (JEP 260). It remains available out-of-the-box in JDK 22, pending the availability of safe supported alternatives.

Over the past several years, we have introduced two standard APIs that are safe and performant replacements for the memory-access methods in sun.misc.Unsafe:

These standard APIs guarantee no undefined behavior, promise long-term stability, and have high-quality integration with the tooling and documentation of the Java Platform (examples of their use are given below). Given the availability of these APIs, it is now appropriate to deprecate and eventually remove the memory-access methods in sun.misc.Unsafe.

Removing the memory-access methods in sun.misc.Unsafe is part of a long-term coordinated effort to ensure that the Java Platform has integrity by default. Other initiatives include placing restrictions on the Java Native Interface (JNI, JEP 472) and on the dynamic loading of agents (JEP 451). These efforts will make the Java Platform more secure and more performant. They will also reduce the risk of application developers becoming trapped on older JDK releases due to libraries that break on newer releases when unsupported APIs are changed.

Description

We are deprecating and removing the memory-access methods in sun.misc.Unsafe in phases:

For a complete list of the memory-access methods and their standard replacements, see JEP 471.

Understanding the use of memory-access methods in sun.misc.Unsafe

The vast majority of Java developers do not use sun.misc.Unsafe explicitly in their own code. However, many applications depend, directly or indirectly, on libraries that use the memory-access methods in sun.misc.Unsafe. In JDK 23 and later, application developers can assess how libraries are affected by the deprecation and removal of these methods by running with a new command line option, --sun-misc-unsafe-memory-access={allow|warn|debug|deny}. This option is similar, in spirit and in form, to the --illegal-access option introduced by JEP 261 in JDK 9. It works as follows:

The default value of the --sun-misc-unsafe-memory-access option is changed from release to release as we proceed through the phases described above:

Developers can also use JDK Flight Recorder (JFR) to identify when memory-access methods are used. When JFR is enabled on the command line, a jdk.DeprecatedInvocation event is recorded whenever a terminally deprecated method is invoked. This event can be used to identify uses of the memory-access methods in sun.misc.Unsafe. For example, here is how to create a JFR recording and then display the jdk.DeprecatedInvocation events:

$ java -XX:StartFlightRecording:filename=recording.jfr ...
$ jfr print --events jdk.DeprecatedInvocation recording.jfr

Further details on this event and its limitations can be found in the JDK 22 release note.

Risks and Assumptions