Using the sun.misc.Unsafe class to do crazy stuff with the JVM

I recently discovered the sun.misc.Unsafe class. Apparently it can be used to manage memory manually, create instances of classes with only private constructors and creating super-large arrays. Is it advisable to use this class? I mean, the class name itself seems to warn developers against using it. But if I do know how to use it the right way, is it advisable to use it to manage memory and all?

If you are starting to think about memory management using Unsafe, you may as well go to C++.

As with Phased’s message above, it’s also not part of the standard JVM, that is, different operating systems will have the sun packages implemented differently, and your code will throw a ClassNotFoundError if the code runs on a non-Sun supported JVM. This essentially defeats the purpose of Java (being able to run on all platforms seamlessly).

Here’s a fairly good SO question and answer to this same question.

The reason why I don’t like C++ is that its syntax is quirky and inconvenient (in my opinion). I want Java’s developer-friendly syntax and I’d like to manage memory manually within Java.

Is there a way around this? Shouldn’t it be fine, as long as the device has the latest version of Java installed?

The sun packages aren’t technically part of Java, per say. They may be removed at any time, Oracle could stop supporting it and just ditch it, rename it to com.oracle.*, etc. The point is is that it’s unsupported and should really be depended on.

If you want to fool around with memory management and special classes, go for it. We’re just not recommending you use it in a project such as a game where other people will use it due to its unpredictable behaviour and future changes.

I find C++ pretty much similar to Java when you scrap off pointers in C++.

By adding the use of Unsafe to your code, you are probably not even going to notice a performance increase, if that is what you are hoping for.

You are pretty much saying no to one of Java’s best features and rolling with your own.

If you are thinking it will increase the performance of your terrain generation, its probably going to either give worse performance or the same performance.

You should continue to improve, you will find that your performance issues are more yourself then the limitations of Java.

It’s not about terrain generation. I just read up about Unsafe and thought that it could be useful. Besides, the ability to manually manage memory in C++ is what makes C++ so powerful, mostly. Wouldn’t it be great if Java could do the same thing? I mean, in Java-based games you could experience performance issues because the garbage collector is trying to do its job. It happens in Minecraft too, sometimes. Does setting an object to null and then calling System.gc() count as freeing memory? From what I know, System.gc() only suggests that the garbage collector should run and does not FORCE the garbage collector to run.

I got this from jaxenter.com:

[quote]unsafe is the only way so far to write high performance/ gc free code in java.
[/quote]
Is this true?

EDIT: I also got this from an interview with some official Oracle dudes:

You shouldnt need to call System.gc(); ever.

It will run its self when needed.

To what I know (also from the above post), you have to manually delete the memory you allocate using Unsafe, this means, you need to add deconstructors like methods to every Java class you use, if you simply let a reference to an object go, the GC will never clean it up, meaning you got a memory leak.

I will stand by my “If you are starting to require memory management in Java, you should change languages”. You are probably going to be limited by something else before memory management in java is your concern.

You are adding an extra level of complexion to your code, where you do not require it.

Apparently Oracle will be introducing a safe version of Unsafe in Java 9 as part of Project Jigsaw. I think there was a talk about that. Most Java developers don’t actually use Unsafe, but some do.

Anyway, yeah, I get the point (get the pun? Memory management…POINTers…? I’m so funny). I guess I’m just gonna forget about Unsafe, then. Still, it’s a pretty interesting class.

Hi,

Some time ago I was inspired by Unsafe too.

But I’ve resisted. :slight_smile:

Just look at this :


    public static long sizeOf( Object object )
    {
        return getUnsafe().getAddress(
                normalize( getUnsafe().getInt( object, 4L ) ) + 12L );
    }

    private static long normalize( int value )
    {
        if ( value >= 0 )
        {
            return value;
        }

        return ( ~0L >>> 32 ) & value;
    }

    public static long toAddress( Object obj )
    {
        Object[] array = new Object[]{obj};
        long baseOffset = getUnsafe().arrayBaseOffset( Object[].class );

        return normalize( getUnsafe().getInt( array, baseOffset ) );
    }

    public static Object fromAddress( long address )
    {
        Object[] array = new Object[]{null};
        long baseOffset = getUnsafe().arrayBaseOffset( Object[].class );
        getUnsafe().putLong( array, baseOffset, address );

        return array[ 0 ];
    }

Isn’t it wonderful?

But, try to keep away from it.

So program should ever want to to perform a full GC at a time of it’s choosing and should always let it happen at some unknowable point in the future outside of its control? For games, say at points where there’s a natural pause in gameplay anyway?

Not allocate once, keep forever memory. A common use-case.

The “real” problem with unsafe usage is: behavior may change across release (distribute a specific VM with program solves this one). Undocumented, so you have to be very careful. And you can put yourself into untested (another be very careful) cases of VM behavior.

In addition the above “not necessarily”, there’s allocations naturally dominated by a container.

GCed objects can memory leak as well. In either case poor design will bite you.

Possibly…depends on a person’s knowledge of, comparative productivity in the languages in question and the overall “problem space” of the program. Many factors here.

Problem space and programmer’s understanding of it. On the whole, you’re way overgeneralizing.

There are things you can’t do without Unsafe.

@Roquen

My reply was more directly towards ShadedVertex, I know in certain scenarios you will probably want to use Unsafe.

My assumption was he wanted to code his entire game using Unsafe for memory management, where in the entire game, he will probably being deallocating a fair bit, which would pretty much mean he needs a deconstructor in every class.

My “If you are starting to require memory management in Java, you should change languages” was more towards him making a game in Java, I feel like his going to be limited by other stuff before he gets limited by the memory management. He also has a lot more other things he needs to learn in OpenGL before he adds the use of Unsafe to manage his memory.

At no point do I see ShadedVertex in the near future require the use of Unsafe, and most likely majority of the users on this forum.

@theagentd if you see this, do you actually use Unsafe to manage any memory at all in We Shall Wake?

@Phased
No, we don’t use Unsafe directly in WSW.

@Roquen
We do however try to call System.gc() after loading since our loading code does generate a bit of garbage and it’s a good time to signal the GC that we’re okay with a garbage collection if it feels like it. =P

Exactly my point. At any natural pause in gameplay, ideally one could say “Do full GC…NOW!”.

I used to think that way… but I now see that the GC is basically so fast and efficient it generally tends to be totally unnoticeable outside of ordinary random noise jitter if just left the hell alone, especially when it’s left to tune itself with target collection times (I set mine to 3ms).

Cas :slight_smile:

Yup. Making sure that your game loop generates minimal garbage, and calling System.gc() whenever they’re not noticeable is good enough. We generate a few kilobytes of garbage each frame (most of it being debugging strings for profiling), and this buildup takes several minutes before a fast, small GC pass can kick in and remove it all in a few milliseconds without a full stop-the-world GC being needed for a long time. At load time go crazy with garbage if it’s faster to write; the call to System.gc() before you start the level will (most likely) clean it all up giving the game loop a garbage-free start.

While debugging my game Shard Master, I found out (might not be true) that the garbage collection acts out on Linux for some reason and it makes the memory usage ridiculously high.

Can anyone confirm this? Or was this just a fluke

It’s still up to you to manage the memory allocated on the native heap (not on the Java heap) typically used by direct NIO buffers. The original poster seems to know the JEP 260, I advise him to forget the Unsafe class and to use sun.misc.Cleaner until a replacement solution is provided. I explained all this with more details here.

In my humble opinion, forcing the garbage collection is a bad idea. If you don’t keep references on useless objects, the garbage collector will do its job smartly most of the time. You can use the pauses in your game to make the most impacting cleanup.