Skip to content

Instantly share code, notes, and snippets.

@advancedxy
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save advancedxy/2ae7c9cc7629f3aeb679 to your computer and use it in GitHub Desktop.
Save advancedxy/2ae7c9cc7629f3aeb679 to your computer and use it in GitHub Desktop.
The simple Sizeof.java from http://www.javaworld.com/article/2077496/testing-debugging/java-tip-130--do-you-know-your-data-size-.html , all credit goes to the original auther
#! /usr/bin/env bash
JAVA_VERSIONS="6 7 8"
CompressFlag="-XX:+UseCompressedOops"
source_file="Sizeof.java"
echo "Downloading Sizeof.java"
curl -o $source_file https://gist.githubusercontent.com/advancedxy/2ae7c9cc7629f3aeb679/raw/197f41e7683ba74f33f858be60c856a3eae529e1/SizeofMod.java
for i in $JAVA_VERSIONS; do
JAVA_HOME=`/usr/libexec/java_home -v 1.$i`
echo "==Hotspot JVM 1.$i non-static filed alignment=="
java -version
for j in `echo "1 2 3"`; do
# in-place edit Sizeof.java
sed -e "s/new DummyClass[0-9]/new DummyClass$j/" -i "" $source_file
echo "=====DummyClass$j====="
javac $source_file
echo "64bit JVM with UseCompressedOops on"
java $CompressFlag Sizeof
echo "64bit JVM without UseCompressedOops"
java `echo $CompressFlag | sed -e "s/+/-/"` Sizeof
done
done
// ----------------------------------------------------------------------------
/**
* A simple class to experiment with your JVM's garbage collector
* and memory sizes for various data types.
*
* @author <a href="mailto:vlad@trilogy.com">Vladimir Roubtsov</a>
*/
public class Sizeof
{
public static void main (String [] args) throws Exception
{
// "warm up" all classes/methods that we are going to use:
runGC ();
usedMemory ();
// array to keep strong references to allocated objects:
final int count = 10000; // 10000 or so is enough for small ojects
Object [] objects = new Object [count];
long heap1 = 0;
// allocate count+1 objects, discard the first one:
for (int i = -1; i < count; ++ i)
{
Object object;
// INSTANTIATE YOUR DATA HERE AND ASSIGN IT TO 'object':
//object = new Object (); // 8 bytes
object = new Integer (i); // 16 bytes
//object = new Long (i); // same size as Integer?
//object = createString (10); // 56 bytes? fine...
//object = createString (9)+' '; // 72 bytes? the article explains why
//object = new char [10]; // 32 bytes
//object = new byte [32][1]; // 656 bytes?!
if (i >= 0)
objects [i] = object;
else
{
object = null; // discard the "warmup" object
runGC ();
heap1 = usedMemory (); // take a "before" heap snapshot
}
}
runGC ();
long heap2 = usedMemory (); // take an "after" heap snapshot:
final int size = Math.round (((float)(heap2 - heap1))/count);
System.out.println ("'before' heap: " + heap1 +
", 'after' heap: " + heap2);
System.out.println ("heap delta: " + (heap2 - heap1) +
", {" + objects [0].getClass () + "} size = " + size + " bytes");
}
// a helper method for creating Strings of desired length
// and avoiding getting tricked by String interning:
public static String createString (final int length)
{
final char [] result = new char [length];
for (int i = 0; i < length; ++ i) result [i] = (char) i;
return new String (result);
}
// this is our way of requesting garbage collection to be run:
// [how aggressive it is depends on the JVM to a large degree, but
// it is almost always better than a single Runtime.gc() call]
private static void runGC () throws Exception
{
// for whatever reason it helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++ r) _runGC ();
}
private static void _runGC () throws Exception
{
long usedMem1 = usedMemory (), usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++ i)
{
s_runtime.runFinalization ();
s_runtime.gc ();
Thread.currentThread ().yield ();
usedMem2 = usedMem1;
usedMem1 = usedMemory ();
}
}
private static long usedMemory ()
{
return s_runtime.totalMemory () - s_runtime.freeMemory ();
}
private static final Runtime s_runtime = Runtime.getRuntime ();
} // end of class
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* A simple class to experiment with your JVM's garbage collector
* and memory sizes for various data types.
*
* @author <a href="mailto:vlad@trilogy.com">Vladimir Roubtsov</a>
*/
public class Sizeof
{
public static class DummyClass1 {}
public static class DummyClass2 extends DummyClass1 {
public boolean x;
}
public static class DummyClass3 extends DummyClass2 {
public byte y;
}
public static void main (String [] args) throws Exception
{
// "warm up" all classes/methods that we are going to use:
runGC ();
usedMemory ();
// array to keep strong references to allocated objects:
final int count = 10000; // 10000 or so is enough for small ojects
Object [] objects = new Object [count];
long heap1 = 0;
// allocate count+1 objects, discard the first one:
for (int i = -1; i < count; ++ i)
{
Object object;
// INSTANTIATE YOUR DATA HERE AND ASSIGN IT TO 'object':
//object = new Object (); // 8 bytes
//object = new Integer (i); // 16 bytes
object = new DummyClass1();
//object = new Long (i); // same size as Integer?
//object = createString (10); // 56 bytes? fine...
//object = createString (9)+' '; // 72 bytes? the article explains why
//object = new char [10]; // 32 bytes
//object = new byte [32][1]; // 656 bytes?!
if (i >= 0)
objects [i] = object;
else
{
object = null; // discard the "warmup" object
runGC ();
heap1 = usedMemory (); // take a "before" heap snapshot
}
}
runGC ();
long heap2 = usedMemory (); // take an "after" heap snapshot:
final int size = Math.round (((float)(heap2 - heap1))/count);
System.out.println ("'before' heap: " + heap1 +
", 'after' heap: " + heap2);
System.out.println ("heap delta: " + (heap2 - heap1) +
", {" + objects [0].getClass () + "} size = " + size + " bytes");
}
// a helper method for creating Strings of desired length
// and avoiding getting tricked by String interning:
public static String createString (final int length)
{
final char [] result = new char [length];
for (int i = 0; i < length; ++ i) result [i] = (char) i;
return new String (result);
}
// this is our way of requesting garbage collection to be run:
// [how aggressive it is depends on the JVM to a large degree, but
// it is almost always better than a single Runtime.gc() call]
private static void runGC () throws Exception
{
// for whatever reason it helps to call Runtime.gc()
// using several method calls:
for (int r = 0; r < 4; ++ r) _runGC ();
}
private static void _runGC () throws Exception
{
long usedMem1 = usedMemory (), usedMem2 = Long.MAX_VALUE;
for (int i = 0; (usedMem1 < usedMem2) && (i < 1000); ++ i)
{
s_runtime.runFinalization ();
s_runtime.gc ();
Thread.currentThread ().yield ();
usedMem2 = usedMem1;
usedMem1 = usedMemory ();
}
}
private static long usedMemory ()
{
return s_runtime.totalMemory () - s_runtime.freeMemory ();
}
private static final Runtime s_runtime = Runtime.getRuntime ();
} // end of class
// ----------------------------------------------------------------------------
==Hotspot JVM 1.6 non-static filed alignment==
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-466.1-11M4716)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-466.1, mixed mode)
=====DummyClass1=====
64bit JVM with UseCompressedOops on
'before' heap: 371568, 'after' heap: 611568
heap delta: 240000, {class Sizeof$DummyClass1} size = 24 bytes
64bit JVM without UseCompressedOops
'before' heap: 524976, 'after' heap: 764976
heap delta: 240000, {class Sizeof$DummyClass1} size = 24 bytes
=====DummyClass2=====
64bit JVM with UseCompressedOops on
'before' heap: 371568, 'after' heap: 611568
heap delta: 240000, {class Sizeof$DummyClass2} size = 24 bytes
64bit JVM without UseCompressedOops
'before' heap: 524976, 'after' heap: 764976
heap delta: 240000, {class Sizeof$DummyClass2} size = 24 bytes
=====DummyClass3=====
64bit JVM with UseCompressedOops on
'before' heap: 371568, 'after' heap: 611568
heap delta: 240000, {class Sizeof$DummyClass3} size = 24 bytes
64bit JVM without UseCompressedOops
'before' heap: 524976, 'after' heap: 844976
heap delta: 320000, {class Sizeof$DummyClass3} size = 32 bytes
==Hotspot JVM 1.7 non-static filed alignment==
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
=====DummyClass1=====
64bit JVM with UseCompressedOops on
'before' heap: 324080, 'after' heap: 484344
heap delta: 160264, {class Sizeof$DummyClass1} size = 16 bytes
64bit JVM without UseCompressedOops
'before' heap: 471488, 'after' heap: 631800
heap delta: 160312, {class Sizeof$DummyClass1} size = 16 bytes
=====DummyClass2=====
64bit JVM with UseCompressedOops on
'before' heap: 325168, 'after' heap: 485432
heap delta: 160264, {class Sizeof$DummyClass2} size = 16 bytes
64bit JVM without UseCompressedOops
'before' heap: 470056, 'after' heap: 710368
heap delta: 240312, {class Sizeof$DummyClass2} size = 24 bytes
=====DummyClass3=====
64bit JVM with UseCompressedOops on
'before' heap: 325040, 'after' heap: 565304
heap delta: 240264, {class Sizeof$DummyClass3} size = 24 bytes
64bit JVM without UseCompressedOops
'before' heap: 470752, 'after' heap: 791064
heap delta: 320312, {class Sizeof$DummyClass3} size = 32 bytes
==Hotspot JVM 1.8 non-static filed alignment==
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
=====DummyClass1=====
64bit JVM with UseCompressedOops on
'before' heap: 525816, 'after' heap: 685816
heap delta: 160000, {class Sizeof$DummyClass1} size = 16 bytes
64bit JVM without UseCompressedOops
'before' heap: 704024, 'after' heap: 864024
heap delta: 160000, {class Sizeof$DummyClass1} size = 16 bytes
=====DummyClass2=====
64bit JVM with UseCompressedOops on
'before' heap: 526088, 'after' heap: 686088
heap delta: 160000, {class Sizeof$DummyClass2} size = 16 bytes
64bit JVM without UseCompressedOops
'before' heap: 704400, 'after' heap: 944400
heap delta: 240000, {class Sizeof$DummyClass2} size = 24 bytes
=====DummyClass3=====
64bit JVM with UseCompressedOops on
'before' heap: 526360, 'after' heap: 766360
heap delta: 240000, {class Sizeof$DummyClass3} size = 24 bytes
64bit JVM without UseCompressedOops
'before' heap: 704776, 'after' heap: 1024776
heap delta: 320000, {class Sizeof$DummyClass3} size = 32 bytes
@advancedxy
Copy link
Author

JVM 6 was downloaded from Apple. JVM 7 and 8 were downloaded from oracle.
It looks like Apple's doesn't respect to UseCompressedOoops option.

I also test a JVM 6 on one server.

java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)

This result is consisted with JVM7 and JVM8 on my local macbook.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment