276

I came across the sun.misc.Unsafe package the other day and was amazed at what it could do.

Of course, the class is undocumented, but I was wondering if there was ever a good reason to use it. What scenarios might arise where you would need to use it? How might it be used in a real-world scenario?

Furthermore, if you do need it, does that not indicate that something is probably wrong with your design?

Why does Java even include this class?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
pdeva
  • 43,605
  • 46
  • 133
  • 171
  • 7
    The JDK devs are currently reviewing this API for possible transformation into a public API in Java 9. If you use it, it's worth taking 5 minutes to fill out the survey: https://www.surveymonkey.com/s/sun-misc-Unsafe . – Andy Lynch Jan 27 '14 at 14:17
  • 2
    This post is being discussed on meta: http://meta.stackoverflow.com/questions/299139/what-to-do-with-close-open-wars – Jon Clements Jul 12 '15 at 19:02

16 Answers16

162

examples

  1. VM "intrinsification." ie CAS (Compare-And-Swap) used in Lock-Free Hash Tables eg:sun.misc.Unsafe.compareAndSwapInt it can make real JNI calls into native code that contains special instructions for CAS

    read more about CAS here http://en.wikipedia.org/wiki/Compare-and-swap

  2. The sun.misc.Unsafe functionality of the host VM can be used to allocate uninitialized objects and then interpret the constructor invocation as any other method call.

  3. One can track the data from the native address.It is possible to retrieve an object’s memory address using the java.lang.Unsafe class, and operate on its fields directly via unsafe get/put methods!

  4. Compile time optimizations for JVM. HIgh performance VM using "magic", requiring low-level operations. eg: http://en.wikipedia.org/wiki/Jikes_RVM

  5. Allocating memory, sun.misc.Unsafe.allocateMemory eg:- DirectByteBuffer constructor internally calls it when ByteBuffer.allocateDirect is invoked

  6. Tracing the call stack and replaying with values instantiated by sun.misc.Unsafe, useful for instrumentation

  7. sun.misc.Unsafe.arrayBaseOffset and arrayIndexScale can be used to develop arraylets,a technique for efficiently breaking up large arrays into smaller objects to limit the real-time cost of scan, update or move operations on large objects

  8. http://robaustin.wikidot.com/how-to-write-to-direct-memory-locations-in-java

more on references here - http://bytescrolls.blogspot.com/2011/04/interesting-uses-of-sunmiscunsafe.html

zudokod
  • 4,074
  • 2
  • 21
  • 24
  • 1
    if you get the address of a field using Unsafe, it can always be changed by the GC, so isnt that operation pretty useless? – pdeva Apr 14 '11 at 20:06
  • get the address for the ones you have allocated – zudokod Apr 15 '11 at 19:52
  • what exactly do you mean by the one *I* have allocated. this seems to be used in places where objects were created using the 'new' operator, thus my question. – pdeva Apr 16 '11 at 09:04
  • 1
    unsafe.allocateMemory and put the value – zudokod Apr 16 '11 at 09:30
  • sun.misc.Unsafe.arrayBaseOffset and arrayIndexScale cannot be used for arraylets, besides eliminating the bounds checking. Access outside the arrays reserved array may result in memory corruption and/or seg. fault. – bestsss Oct 28 '11 at 21:38
  • 1
    Regarding the point 2, I would like to know how can you invoke the constructor as any other method call? Because I did not find any way of doing that unless in bytecodes. – Miguel Gamboa Nov 23 '12 at 13:22
32

Just from running a search in some code search engine I get the following examples:

Simple class to obtain access to the {@link Unsafe} object. {@link Unsafe} * is required to allow efficient CAS operations on arrays. Note that the versions in {@link java.util.concurrent.atomic}, such as {@link java.util.concurrent.atomic.AtomicLongArray}, require extra memory ordering guarantees which are generally not needed in these algorithms and are also expensive on most processors.

  • SoyLatte - java 6 for osx javadoc excerpt

/** Base class for sun.misc.Unsafe-based FieldAccessors for static fields. The observation is that there are only nine types of fields from the standpoint of reflection code: the eight primitive types and Object. Using class Unsafe instead of generated bytecodes saves memory and loading time for the dynamically-generated FieldAccessors. */

  • SpikeSource

/* FinalFields that are sent across the wire .. how to unmarshall and recreate the object on the receiving side? We don't want to invoke the constructor since it would establish values for final fields. We have to recreate the final field exactly like it was on the sender side. The sun.misc.Unsafe does this for us. */

There are many other examples, just follow the above link...

Asaf
  • 6,384
  • 1
  • 23
  • 44
25

Interesting, I'd never even heard of this class (which is probably a good thing, really).

One thing that jumps to mind is using Unsafe#setMemory to zeroize buffers that contained sensitive information at one point (passwords, keys, ...). You could even do this to fields of "immutable" objects (then again I suppose plain old reflection might do the trick here too). I'm no security expert though so take this with a grain of salt.

Mike Daniels
  • 8,582
  • 2
  • 31
  • 44
  • 4
    `I'd never even heard of this class` ... I've told you about it so many times! *sigh* + :( – Tim Bender Apr 11 '11 at 21:19
  • 7
    There wouldn't be any point, since Java uses a copying generational garbage collector and your sensitive information will quite probably already be located somewhere else in 'free' memory waiting to be overwritten. – Daniel Cassidy Apr 15 '11 at 08:34
  • 39
    Never heard of it either, but I love their `park()` documentation: "Block current thread, returning when a balancing unpark occurs, or a balancing unpark has already occurred, or the thread is interrupted, or, if not absolute and time is not zero, the given time nanoseconds have elapsed, or if absolute, the given deadline in milliseconds since Epoch has passed, _or spuriously (i.e., returning for no 'reason')_". Almost as good as "memory is freed when the program exits, or, at random intervals, whichever comes first". – aroth Apr 15 '11 at 11:38
  • 1
    @Daniel, interesting, I hadn't considered that. Now you can see why I'm not a security expert. :) – Mike Daniels Apr 16 '11 at 23:27
24

Based on a very brief analysis of the Java 1.6.12 library using eclipse for reference tracing, it seems as though every useful functionality of Unsafe is exposed in useful ways.

CAS operations are exposed through the Atomic* classes. Memory manipulations functions are exposed through DirectByteBuffer Sync instructions (park,unpark) are exposed through the AbstractQueuedSynchronizer which in turn is used by Lock implementations.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • The AtomicXXXUpdaters are too slow and when you really need them: CAS - you can't afford to use them actually. If you are going to do the metal you won't be using the abstraction levels and numerous of checks. Failing the CAS is a bad in a loop esp. when the hardware decides to mispredict the branch (due to high contention) but having few more compare/branches just hurts. Park/Unpark are exposed through `LockSupport` not AQS (that latter is more of a lock impl. than park/unpark) – bestsss Jun 05 '14 at 13:31
21

Unsafe.throwException - allows to throw checked exception without declaring them.

This is useful in some cases where you deal with reflection or AOP.

Assume you Build a generic proxy for a user defined Interface. And the user can specify which exception is thrown by the implmentation in a special case just by declaring the exception in the interface. Then this is the only way I know, to rise a checked exception in the Dynamic Implementation of the Interface.

import org.junit.Test;
/** need to allow forbidden references! */ import sun.misc.Unsafe;

/**
 * Demonstrate how to throw an undeclared checked exception.
 * This is a hack, because it uses the forbidden Class {@link sun.misc.Unsafe}.
 */
public class ExceptionTest {

    /**
     * A checked exception.
     */
    public static class MyException extends Exception {
        private static final long serialVersionUID = 5960664994726581924L;
    }

    /**
     * Throw the Exception.
     */
    @SuppressWarnings("restriction")
    public static void throwUndeclared() {
        getUnsafe().throwException(new MyException());
    }

    /**
     * Return an instance of {@link sun.misc.Unsafe}.
     * @return THE instance
     */
    @SuppressWarnings("restriction")
    private static Unsafe getUnsafe() {
        try {

            Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
            singleoneInstanceField.setAccessible(true);
            return (Unsafe) singleoneInstanceField.get(null);

        } catch (IllegalArgumentException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (SecurityException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (NoSuchFieldException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (IllegalAccessException e) {
            throw createExceptionForObtainingUnsafe(e);
        }
    }

    private static RuntimeException createExceptionForObtainingUnsafe(final Throwable cause) {
        return new RuntimeException("error while obtaining sun.misc.Unsafe", cause);
    }


    /**
     * scenario: test that an CheckedException {@link MyException} can be thrown
     * from an method that not declare it.
     */
    @Test(expected = MyException.class)
    public void testUnsingUnsaveToThrowCheckedException() {
        throwUndeclared();
    }
}
Ralph
  • 118,862
  • 56
  • 287
  • 383
  • 14
    you can do the same w/ `Thread.stop(Throwable)` no need for unsafe, in the same thread you can throw anything anyways (there is no compile check) – bestsss Oct 28 '11 at 21:34
  • You can do this purely through bytecode (Or use Lomboc to do it for you) – Antimony Aug 04 '12 at 18:20
  • 1
    @bestsss That method has been stubbed out and throws an `UnsupportedOperationException` in the current thread as of Java 8. However, the no-argument version that throws `ThreadDeath` still works. – gparyani Jun 02 '14 at 03:38
  • @damryfbfnetsi, I have not followed core jdk discussions for quite some time and no plans to move to java 8. Yet, this is quite a puzzling idea since it's trivial to be implemented by bytecode generation anyways, unless now the verifier actually checks if they method declares the throwables... but that might be backward incompatible as metadata about thrown exception was free to be discarded. – bestsss Jun 05 '14 at 13:19
11

Class Unsafe

A collection of methods for performing low-level, unsafe operations. Although the class and all methods are public, use of this class is limited because only trusted code can obtain instances of it.

One use of it is in java.util.concurrent.atomic classes:

Community
  • 1
  • 1
Margus
  • 19,694
  • 14
  • 55
  • 103
7

For efficient memory copy (faster to copy than System.arraycopy() for short blocks at least); as used by Java LZF and Snappy codecs. They use 'getLong' and 'putLong', which are faster than doing copies byte-by-byte; especially efficient when copying things like 16/32/64 byte blocks.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • 1
    Doh, arraycopy uses SSE loops on x86-64 which are better than `getLong/putLong` (and you have to calculate the address as well) – bestsss Jun 05 '14 at 13:34
  • Have you actually measured this? For shorter blocks I see consistently better performance on x86-64 when using combination of `getLong`/`putLong`: ideally I would prefer `System.arraycopy()` for simplicity and all; but actual testing showed otherwise for cases I have tested. – StaxMan Jun 10 '14 at 18:13
  • yes using unsafe I could not any meaningful performance out of deflate impl. For several bytes long copies over large arrays get/putLong might work indeed when the compiler has to check lengths. Some impl. add memory fence past System.arrayCopy (can be disabled/enabled though), so that could be the real culprit. – bestsss Jun 10 '14 at 19:54
  • Ok. It is possible that newer JDKs have changed this; originally when I did observe faster operation (with JDK 1.6) I was surprised too. Or perhaps I am forgetting some specific difference in usage. These are tricky (and possibly unstable) optimizations, even when they do work, and it is essential to measure effects. – StaxMan Jun 12 '14 at 20:46
6

Off-heap collections may be useful for allocating huge amounts of memory and deallocating it immediately after use without GC interference. I wrote a library for working with off-heap arrays/lists based on sun.misc.Unsafe.

alexkasko
  • 4,855
  • 1
  • 26
  • 31
6

Use it to access and allocate large amounts of memory efficiently, such as in your very own voxel engine! (i.e. Minecraft-style game.)

In my experience, the JVM is often unable to eliminate bounds-checking in place you truly need it. For example, if you're iterating over a large array, but the actual memory access is tucked underneath a non-virtual* method call in the loop, the JVM may still perform a bounds check with each array access, rather than once just before the loop. Thus, for potentially large performance gains, you can eliminate JVM bounds-checking inside the loop via a method which employs sun.misc.Unsafe to access the memory directly, making sure to do any bounds-checking yourself at the correct places. (You are gonna bounds check at some level, right?)
*by non-virtual, I mean the JVM shouldn't have to dynamically resolve whatever your particular method is, because you've correctly guaranteed that class/method/instance are some combination of static/final/what-have-you.

For my home-grown voxel engine, this resulted in a dramatic performance gain during chunk generation and serialization (iow places where I was reading/writing to the entire array at once). Results may vary, but if a lack of bounds-elimination is your problem, then this will fix it.

There are some potentially major problems with this: specifically, when you provide the ability to access memory without bounds-checking to clients of your interface, they will probably abuse it. (Don't forget that hackers can also be clients of your interface... especially in the case of a voxel engine written in Java.) Thus, you should either design your interface in a way such that memory access cannot be abused, or you should be extremely careful to validate user-data before it can ever, ever mingle with your dangerous interface. Considering the catastrophic things a hacker can do with unchecked memory access, it's probably best to take both approaches.

Philip Guin
  • 1,452
  • 15
  • 21
6

I was recently working on reimplementing the JVM and found that a surprising number of classes are implemented in terms of Unsafe. The class is mostly designed for the Java library implementers and contains features that are fundamentally unsafe but necessary for building fast primitives. For example, there are methods for getting and writing raw field offsets, using hardware-level synchronization, allocating and freeing memory, etc. It is not intended to be used by normal Java programmers; it's undocumented, implementation-specific, and inherently unsafe (hence the name!). Moreover, I think that the SecurityManager will disallow access to it in almost all cases.

In short, it mainly exists to allow library implementers access to the underlying machine without having to declare every method in certain classes like AtomicInteger native. You shouldn't need to use or worry about it in routine Java programming, as the whole point is to make the rest of the libraries fast enough that you wouldn't need that sort of access.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
5

We have implemented huge collections like Arrays,HashMaps,TreeMaps using Unsafe.
And to avoid/minimize the fragmentation, we implemented memory allocator using the concepts of dlmalloc over unsafe.
This helped us to gain the performance in concurrency.

pradipmw
  • 191
  • 2
  • 11
3

Unsafe.park() and Unsafe.unpark() for the construction of custom concurrency control structures and cooperative scheduling mechanisms.

andersoj
  • 22,406
  • 7
  • 62
  • 73
1

Haven't used it myself, but I suppose if you have a variable that is only occasionally read by more than one thread (so you don't really want to make it volatile) you could use the putObjectVolatile when writing it in the main thread and readObjectVolatile when doing the rare reads from other threads.

Matt Wonlaw
  • 12,146
  • 5
  • 42
  • 44
  • 1
    but according to the discussion on the thread below, uncontented volatile are almost as fast as non-volatiles anyway http://stackoverflow.com/questions/5573782/is-volatile-of-no-use-on-x86-processors – pdeva Apr 07 '11 at 03:17
  • you cannot replace volatile semantics with plain writes and volatile reads... this is a recipe for disaster as it may work in one settings but not another. If you are looking to have volatile semantics with a single writer thread you can use AtomicReference.lazySet on the writing thread and get() on the readers(see this [post](http://psy-lob-saw.blogspot.com/2012/12/atomiclazyset-is-performance-win-for.html) for a discussion on the topic). Volatile reads are relatively cheap, but not free, see [here](http://brooker.co.za/blog/2012/09/10/volatile.html) . – Nitsan Wakart Jan 09 '13 at 13:12
  • "...you could use the putObjectVolatile when writing it..." I wasn't suggesting plain writes. – Matt Wonlaw Jan 09 '13 at 14:15
1

One example of its use is the random method, which calls the unsafe to change the seed.

This site also has also some uses of it.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
woliveirajr
  • 9,433
  • 1
  • 39
  • 49
1

You need it if you need to replace functionality provided by one of the classes which uses it currently.

This can be custom/faster/more compact serialization/deserialization, a faster/larger buffer/resizable version of ByteBuffer, or adding an atomic variable e.g. one not supported currently.

I have used it for all of these at some time.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

The object appears to be availability to work at a lower level than what Java code typically allows for. If you're coding a high level application then the JVM abstracts memory handling and other operations away from the code level so its easier to program. By using the Unsafe library you're effectively completing low-level operations that would typically be done for you.

As woliveirajr stated "random()" uses Unsafe to seed just as many other operations will use the allocateMemory() function included in Unsafe.

As a programmer you probably could get away with never needing this library but having strict control over low-level elements does come in handy (that's why there is still Assembly and (to a lesser extent) C code drifting around in major products)

Grambot
  • 4,370
  • 5
  • 28
  • 43