Resurrecting sun.misc.Unsafe

Here’s one that only the hardcore Java hackers will enjoy. Perhaps you are already familiar with sun.misc.Unsafe. This heavily protected internal class provides access to a number of low-level memory operations and system functions that are generally hidden away from user-code executing in the JRE. If you’ve never heard of it before (or even if you have) then I encourage you to read this article to get an idea about the sort of things that can be done using ‘Unsafe‘. Note that we are talking about very low-level operations here. Operations where if you make a mistake, you won’t just get a simple ‘Exception‘ complaining that you did something bad. Instead you’re liable to bring the entire JVM to a crashing halt if you do something wrong (it’s called ‘Unsafe‘ for a reason, after all), so you should proceed only if you’re sure you know what you are doing.

Also note that the method described in the other article for getting your hands on an instance of ‘Unsafe‘ no longer works. Using the latest JDK, the following code will not work (you’ll get compiler errors for even trying to import sun.misc.Unsafe):

private static Unsafe getUnsafeInstance() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
    IllegalAccessException {
    Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
    theUnsafeInstance.setAccessible(true);
    return (Unsafe) theUnsafeInstance.get(Unsafe.class);
 }

Here is a variant that still works:

	public static Object getUnsafe() {
		try {
			Class unsafeClass = Class.forName("sun.misc.Unsafe");
			Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
			unsafeField.setAccessible(true);
			Object unsafeObj = unsafeField.get(unsafeClass);
			
			return unsafeObj;
		}
		catch (Exception e) {
			return null;//UNSAFE_ERROR_CODE;
		}
	}

Note that as importing sun.misc.Unsafe now causes a compiler error, it is only possible to return an Object reference to the ‘Unsafe‘ instance. This means that any method that you want to call on it must be done through reflection, which is tedious at best. Luckily, I’ve taken care of this tedious bit for you, and created a wrapper that provides the same public API as sun.misc.Unsafe and uses reflection to delegate method calls to the real ‘Unsafe‘ instance. The source code for this utility is quite long and not very interesting, so I’m not going to post it here. Instead you can use this direct link to download a copy.

Here is a simple example of how to use this class to perform some basic tasks:

		System.out.println("Testing sun.misc.Unsafe...");
		double[] averages = {-777.0, -777.0, -777.0};
		UnsafeUtil util = new UnsafeUtil();
		System.out.println("addressSize=" + util.addressSize() + ", pageSize=" + util.pageSize());
		
		long memPointer = util.allocateMemory(1024);
		long memPointer2 = util.allocateMemory(1024);
		System.out.println("1K memory blocks at addresses:  " + memPointer + ", " + memPointer2);
		
		//valid copy
		util.copyMemory(memPointer, memPointer2, 1024);
		
		//invalid copy
		//util.copyMemory(memPointer, memPointer2, 1024000);
		
		int result = util.getLoadAverage(averages, 1);
		System.out.println("getLoadAverage:  Result=" + result + ", averages=" + averages[0] + ", " + averages[1] + ", " + averages[2]);

Do note that if you uncomment the “invalid copy” line then running this code will very likely crash your JVM. As noted above, you should use this utility with caution, particularly if you are running it in an environment shared by other Java code.

And why do all this when Sun (now Oracle) clearly does not want people mucking around with this class? Because ultimately power belongs in the hands of developers. All developers, not just the select few chosen to work on privileged system code.

This entry was posted in coding, java and tagged , . Bookmark the permalink.

2 Responses to Resurrecting sun.misc.Unsafe

  1. Joe Bloggs says:

    … you killed the only reason (performance!) to use Unsafe because you think your IDE is the compiler. Try changing your IDE settings for restricted classes and lo and behold it works again without any reflection…

  2. Sungwan Jung says:

    Thank u. I read your article and it helped me up. I leave a question with wondering if you could read this comment. Actually, the wrapper code above doesn’t work correctly at least in my case. When UnsafeUtil is instantiated, the instance returns an exception. I’m trying this with jdk 1.7.0_51, android sdk 22.3, Target SDK Android 4.3. Old article and my poor English.. just quietly hope your short advise. Thank you in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>