Skip to main content

Java - Getting the memory size of an object.

Because the way Java language and the way JVMs are implemented, this apparently trivial task is more complex than it may seem specially when compared to C++ where all objects have a size() method. Java memory architecture is built to abstract the developer from direct manipulation of memory so that the developer can focus on more relevant tasks, this comes with a price.

There are 3 basic approaches you can take in order to do this all with their pros and cons:
  • Memory guess (Heap Size prior object creation - Heap Size after object creation = Object Size)
  • Java Instrumenting Query
  • Serialization

Memory Guess
This is the simplest approach because of the fact that you have a pretty easy access to the Heap Size via:
 Runtime.getRuntime().totalMemory();


The issue with this approach is that you cannot control what is being thrown into the heap at a given time, JVM is shared by a lot of processes that run in a given machine so this is a error prone approach that is not recommended.

Java Instrumenting Query

Starting on Java 5, all JVM have built in instrumentation features . This features can be used to monitor objects size in memory by creating an agent and setting it up for the JVM. This is by far the most precise method of getting the object's size from memory, but it's by no means the easiest/straight-forward. Another drawback is that this may change depending on the JVM you are using (the next example applies only to Oracle's Standard JVM 5 )

The agent looks something like this:

import java.lang.instrument.*;
import com.somepackage.SomeClass;

public class MyAgent {
  public static void premain(String args, Instrumentation inst) {
    SomeClass obj = new SomeClass();
    long size = inst.getObjectSize(obj);
    System.out.println("Bytes used by object: " + size);
  }
}
Then you need to register the agent to the JVM by initializing the application with the folowing parameters:

java -javaagent:agent.jar

That will cause the agent to be registered on the JVM instrumenting layer where it will be able to monitor object's size.
Next you can access these feature with something like:
public class MyAgent {
  private static volatile Instrumentation globalInstr;
  public static void premain(String args, Instrumentation inst) {
    globalInstr = inst;
  }
  public static long getObjectSize(Object obj) {
    if (globalInstr == null)
      throw new IllegalStateException("Agent not initted");
    return globalInstr.getObjectSize(obj);
  }
}
As you have certainly noticed this is no as intuitive as it may seem.
Serialization
This technique uses Java's serialization features to calculate the objects size. This is not the most precise way to do it because memory specific serialization works in a slightly different way than regular object serialization but its a pretty good approximation. One drawback of this approach is that it requires the object to be measured to be Serializable.
This is how a method that mesures the size would look like:
public long sizeOf(Serializable object){
 if (object == null) {
  return 0;
 }

 try{
  final ByteCountingOutputStream out = new ByteCountingOutputStream();
  new ObjectOutputStream(out).writeObject(object);
  out.close();
  return out.size();
 }catch (IOException e){
  if (log.isWarnEnabled()){
   log.warn("Unable to determine object size: " + object.toString(), e);
  }
  return -1;
 }
}
One of the greatest drawbacks of this simple approach is that OutputSreams in general are one of the most commonly known resource hogs in Java so you should treat them with care.

Comments

Popular posts from this blog

¿Que tienen los cuchillos de obsidiana y el Nearshore en común?

Presentacion Aparicion en Campus Night Jalisco Nov 2016 Como siempre me gustaría empezar esta noche con una historia, disculpen uds la insistencia, pero esto es lo que los cuenta cuentos hacemos. Al terminar les prometo que la historia es bastante relevante con lo el tema que queremos tratar. Este es parte de una historia es solo un fragmento plasmado en el Códice Boturini conocido también como la Tira de la Peregrinación que narra la migración de los Chichimecas de su lugar de origen, Aztlán,  hacia su destino final, la tierra prometida de Teoculhuacan. El viaje inicia como muchos viajes conocidos, con un personaje misterioso y muy poderoso que convence a un grupo de aventureros a embarcarse en una aventura, en ese caso éste personaje no es otro que el mismísimo Huitzilopozchtli, el dios de la guerra, el sol y los sacrificios humanos, nuestro Gandalf mesoamericano. Nuestra historia comienza pasados más de 2 siglos dentro de este viaje tras muchas peripecias y percanc...

Of dogs, economy and tribalism.

I'm a dog guy... I love dogs since I was a kid. Back then my dad adopted a gorgeous white Grand Dane we called, ironically, "Pitufo" (that's the Latin American equivalent of Smurf). He was this gargantuan behemoth cuteness. He loved to jump on people, it was his way of being friendly. You can imagine that not everyone understood that as a friendly gesture, though; a 1.82m tall beast jumping with his paws on your chest and trying to lick your face is probably a scary thing to experience, special coming from a dog you don't know. One day Smurf escaped from my yard and decided to say hi to a passing young couple. The young woman welcome my dogs gesture by screaming like a rape victim, so picture the scene... Small young woman screaming, completely freaked out and covering her face while huge dog drooled and jumped around her. It indeed look bad for Smurf. To make things worst a policeman was witnessing the scene from about a block away. After the policeman approache...