I search and found there are different way of checking object memory created for Java.
1. One is done by checking Runtime memory available
https://stackoverflow.com/a/383597
2. The other one is using the ByteArrayOutputStream to check
https://stackoverflow.com/a/38188384/3286489
So I have written a program using both approach and check if they are the same
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class LotsOfBooleans implements Serializable
{
boolean a0;
}
class LotsOfInts implements Serializable
{
int a0;
}
public class Test
{
private static final int SIZE = 1000000;
public static void main(String[] args) throws Exception
{
LotsOfBooleans[] first = new LotsOfBooleans[SIZE];
LotsOfInts[] second = new LotsOfInts[SIZE];
System.gc();
long startMem = getMemory();
for (int i=0; i < SIZE; i++)
{
first[i] = new LotsOfBooleans();
}
System.gc();
long endMem = getMemory();
System.out.println ("Size for LotsOfBooleans (by checking Runtime) : " + (endMem-startMem));
System.gc();
startMem = getMemory();
for (int i=0; i < SIZE; i++)
{
second[i] = new LotsOfInts();
}
System.gc();
endMem = getMemory();
System.out.println ("Size for LotsOfInts (by checking Runtime memory) : " + (endMem-startMem));
System.out.println ("Size for LotsOfBooleans (using ByteArrayOutputStream) : " + getBytes(first).length);
System.out.println ("Size for LotsOfInts (using ByteArrayOutputStream) : " + getBytes(second).length);
// Make sure nothing gets collected
long total = 0;
for (int i=0; i < SIZE; i++)
{
total += (first[i].a0 ? 1 : 0) + second[i].a0;
}
System.out.println(total);
}
private static long getMemory()
{
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
private static byte[] getBytes(Object o) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(o);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
// ignore close exception
}
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}
return null;
}
}
I compile it using https://www.tutorialspoint.com/compile_java_online.php
The result as below
$javac Test.java
$java -Xmx128M -Xms16M Test
Size for LotsOfBooleans (by checking Runtime) : 15914240
Size for LotsOfInts (by checking Runtime memory) : 15999984
Size for LotsOfBooleans (using ByteArrayOutputStream) : 7000072
Size for LotsOfInts (using ByteArrayOutputStream) : 10000064
0
From the result, clearly shows they are different. I have the feeling that ByteArrayOutputStream
is more accurate. But the checking Runtime
approach is by @jon-skeet, which is from a renown StackoverFlow contributor.
So which one should I refer to?
Or both of them are correct, but referring to a different size of object (mind explaining how they are different if both are correct?
If both approach is not right, do suggest what is a good way to know the size of my object in Java?