Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Dangerous Code: How to be Unsafe with Java Classes & Objects in Memory

living dangerously

Let’s get laid out…the class and object structure of Java in memory

Have you ever wondered about the internals of Java memory management? Do you ask yourself weird questions like:

  • How much space does a class take up in memory?
  • How much space do my objects consume in machine memory?
  • What’s the deal with the alignment of object properties in memory?

If these questions sound familiar, then you are in the right place. For Java geeks like us over here at RebelLabs, these mysterious questions have been orbiting our minds for a long time: if you are interested knowing more about the instrumentation of classes, knowing how classes are laid out will make it easier to get some specific fields from memory, or hack these fields within memory on the fly. This means that you can actually change the data or even the code within the memory!

Other points that might be striking your interest are “Off-Heap Memory” and “High Performance Serialization” implementations, which are a couple of good samples based on the object memory structure. This covers the ways to access memory addresses of classes and their instances, the layouts of these classes and instances in memory, along with a detailed explanation on the layouts of the object fields. We’re hoping to explain the content as simply as possible, but even so this article isn’t for Java beginners and knowledge of some Java programming principles are needed.

N.B. The writing below on the layouts of classes and objects are specific to Java SE 7, so it’s not recommended to automatically assume that any of it will be applicable in past or future versions of Java. For your convenience, we’ve placed the sample code for this article in a GitHub project for convenience, which you can find here: https://github.com/serkan-ozal/ocean-of-memories/tree/master/src/main/java/com/zeroturnaround/rebellabs/oceanofmemories/article1

What is the way of Direct Memory Access in Java?

Java was initially designed as a safe, managed environment. Nevertheless, Java HotSpot VM contains a “backdoor” that provides a number of low-level operations to manipulate memory and threads directly. This backdoor class – sun.misc.Unsafe – is widely used by JDK itself in packages like java.nio or java.util.concurrent. However, using this backdoor is certainly not suggested for use in the production environment, because this API is extremely dangerous, non-portable, and volatile. The Unsafe class provides an easy way to look into HotSpot JVM internals and to do some tricks. Sometimes it can be used to study VM internals without C++ code debugging, sometimes it can be leveraged for profiling and development tools.

How to be Unsafe
The sun.misc.Unsafe class was so unsafe that JDK developers added special checks to restrict access to it. Its constructor is private and the caller of the factory method getUnsafe() should be loaded by Bootloader. As you can see at line 8 in the snippet below, this goodie is not even loaded by any class loader, so its class loader is null. It will throw a SecurityException to prevent intruders.

public final class Unsafe {
   ...
   private Unsafe() {}
   private static final Unsafe theUnsafe = new Unsafe();
   ...
   public static Unsafe getUnsafe() {
      Class cc = sun.reflect.Reflection.getCallerClass(2);
      if (cc.getClassLoader() != null)
          throw new SecurityException("Unsafe");
      return theUnsafe;
   }
   ...
}

Fortunately there is theUnsafe field that can be used to retrieve the Unsafe instance. We can easily write a helper method to do this via reflection, as seen below. (http://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/)

public static Unsafe getUnsafe() {
   try {
           Field f = Unsafe.class.getDeclaredField("theUnsafe");
           f.setAccessible(true);
           return (Unsafe)f.get(null);
   } catch (Exception e) { 
       /* ... */ 
   }
}

Some useful features of Unsafe

  1. VM “intrinsification” i.e. CAS (compare-and-swap) used in Lock-Free Hash Tables. For example the compareAndSwapInt method makes real JNI calls into native code that contains special instructions for CAS. You can 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 (by “allocateInstance” method) and then interpret the constructor invocation as any other method call.

  3. You can track the data from the native address. It’s 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. With the allocateMemory method, memory can be allocated from off-heap. For example, the DirectByteBuffer constructor internally calls it when the allocateDirect method is invoked.

  5. The methods, 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.

In the next section, as we get the memory address of a class, we give some examples of using “Unsafe”.