i have a list of simples pojos (a User class) with about 15 simple fields & 1 arrayList. Those represent users & maybe 100 or 1000 of them will be store in memory in
You can calculate the memory used by the JRE before and after you create your object, in order to approximate how many bytes are being used by your object.
System.gc();
System.runFinalization();
Thread.sleep(1000);
long before = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
//build object here
System.gc();
System.runFinalization();
Thread.sleep(1000);
long after = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long objectSize = after - before;
There is JOL (Java Object Layout) utility library that can analyze object layout and memory footprint.
Add dependency to your project (for example with gradle compile 'org.openjdk.jol:jol-core:0.9'
) and then you can use helper classes to print or check memory footprint of concrete object.
// Print VM details
System.out.println(VM.current().details());
// Create new object (this can be your own data class)
Map<String, Long> o = new HashMap<>();
o.put("key1", 123L);
// To check object size (for example: from unit test)
System.out.println("Shallow size: " + VM.current().sizeOf(o));
System.out.println("Total size: " + GraphLayout.parseInstance(o).totalSize());
System.out.println();
// To print object details
System.out.println(ClassLayout.parseInstance(o).toPrintable());
System.out.println(GraphLayout.parseInstance(o).toPrintable());
System.out.println(GraphLayout.parseInstance(o).toFootprint());
The output of this example on Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
, java version "1.8.0_191"
:
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Shallow size: 48
Total size: 232
java.util.HashMap object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 52 99 6a (00000001 01010010 10011001 01101010) (1788432897)
4 4 (object header) 2d 00 00 00 (00101101 00000000 00000000 00000000) (45)
8 4 (object header) a3 37 00 f8 (10100011 00110111 00000000 11111000) (-134203485)
12 4 java.util.Set AbstractMap.keySet null
16 4 java.util.Collection AbstractMap.values null
20 4 int HashMap.size 1
24 4 int HashMap.modCount 1
28 4 int HashMap.threshold 12
32 4 float HashMap.loadFactor 0.75
36 4 java.util.HashMap.Node[] HashMap.table [(object), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
40 4 java.util.Set HashMap.entrySet null
44 4 (loss due to the next object alignment)
Instance size: 48 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
java.util.HashMap@2d6a9952d object externals:
ADDRESS SIZE TYPE PATH VALUE
7410cb2b8 24 java.lang.Long .table[0].value 123
7410cb2d0 5383088 (something else) (somewhere else) (something else)
7415ed680 48 java.util.HashMap (object)
7415ed6b0 24 java.lang.String .table[0].key (object)
7415ed6c8 24 [C .table[0].key.value [k, e, y, 1]
7415ed6e0 80 [Ljava.util.HashMap$Node; .table [(object), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
7415ed730 32 java.util.HashMap$Node .table[0] (object)
java.util.HashMap@2d6a9952d footprint:
COUNT AVG SUM DESCRIPTION
1 24 24 [C
1 80 80 [Ljava.util.HashMap$Node;
1 24 24 java.lang.Long
1 24 24 java.lang.String
1 48 48 java.util.HashMap
1 32 32 java.util.HashMap$Node
6 232 (total)
If you want a simple test, you can set the new size to be large and do the following. This only works if your new size is much larger than the data you are creating. e.g.
-XX:NewSize=1g -verbosegc
The value will be correct provided you don't see any GC.
long before = Runtime.getRuntime().freeMemory();
//build object here
long used = before - Runtime.getRuntime().freeMemory();
Note: this assumes you don't generate an temporary objects.
You can write them to ByteOutputStream
, then get byte array and check its length. This will work if your pojos are Serializable.