0

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?

Elye
  • 53,639
  • 54
  • 212
  • 474
  • The answer largely depends on what you mean by "size of an object" and what you are going to use this information for (capacity planning?). Why do you need to know this? – Thilo Jan 09 '20 at 13:01
  • The BAOS method gives you the size of the serialized object. This is very different from an in-memory layout. It is closer to the on-disk size the object would have. – Thilo Jan 09 '20 at 13:05
  • Both actually. In-memory and file (e.g. I plan to know how much memory it is using, and plan to write into file). I thought they are correlated, so didn't know they are different. If I have to choose one, I would go for In-memory. – Elye Jan 09 '20 at 13:09
  • @Thilo, https://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object doesn't help answer me, as I want to calculate it in my Android application – Elye Jan 09 '20 at 13:17

0 Answers0