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.

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 percances los Chichimecas…

Is the World Shrinking?

Humans are a social primates; that’s an evolutive fact that has been around for a while to the point that it is now collective common knowledge. This presents an obvious advantage if you add to the mix the fact that not only we create bonds to other close members of our species but we like to relate with basically any other members that we came across. We have evolved to be nice with each other. This grants us the ability to extend our influence and our inner circle beyond social, cultural and geographical constraints.

This has been an interesting phenomenon that has been studied for quite a long time. We have been tracing our origins with family trees and trying to find out what we fit in the big picture of society. One of those attempts to understand it is the pretty famous 6 degrees of separation (Also known as the Kevin Bacon's degrees of Separation) idea. The basic idea is this; Imagine that every person in the planet is a dot, and every relationship between them are lines t…