jdk: java 官网上下载的,HotSpot 虚拟机java
java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
确认编译时是 32 位仍是 64 位,对测试结果有影响。x86 为 32 位, amd64 为 64 位,其他我不知道git
System.out.println(System.getProperty("os.arch"));
在包名路径下执行一下命令进行打包(注意修改相应的包名):github
jar cvfm SizeOfObject.jar manifest.mf org/seal_de/SizeOfObject.class
在运行测试程序的时候,添加 vm 参数jvm
-javaagent:{jar包路径}\SizeOfObject.jar
public class MemoryTest { /** * -javaagent:{jar包路径}\SizeOfObject.jar -XX:+UseCompressedOops * 使用指针压缩,在必定状况下64位HotSpot jvm默认指针压缩 * *Output: *amd64 *Object: 16 * *include one int: 16 *include two int: 24 *include three int: 24 * *include one object: 16 *include one object: 24 */ static void test1() { System.out.println(System.getProperty("os.arch")); System.out.printf("%-30s%9d\n", "Object:", SizeOfObject.sizeOf(new Object())); System.out.println(); System.out.printf("%-30s%9d\n", "include one int:", SizeOfObject.sizeOf(new IntegerTestOne())); System.out.printf("%-30s%9d\n", "include two int:", SizeOfObject.sizeOf(new IntegerTestTwo())); System.out.printf("%-30s%9d\n", "include three int:", SizeOfObject.sizeOf(new IntegerTestThree())); System.out.println(); System.out.printf("%-30s%9d\n", "include one object:", SizeOfObject.sizeOf(new ReferenceTestOne())); System.out.printf("%-30s%9d\n", "include one object:", SizeOfObject.sizeOf(new ReferenceTestTwo())); } /** * -javaagent:{jar包路径}\SizeOfObject.jar -XX:-UseCompressedOops * 不使用指针压缩 * *Output: *amd64 *Object: 16 * *include one int: 24 *include two int: 24 *include three int: 32 * *include one object: 24 *include one object: 32 */ static void test2() { System.out.println(System.getProperty("os.arch")); System.out.printf("%-30s%9d\n", "Object:", SizeOfObject.sizeOf(new Object())); System.out.println(); System.out.printf("%-30s%9d\n", "include one int:", SizeOfObject.sizeOf(new IntegerTestOne())); System.out.printf("%-30s%9d\n", "include two int:", SizeOfObject.sizeOf(new IntegerTestTwo())); System.out.printf("%-30s%9d\n", "include three int:", SizeOfObject.sizeOf(new IntegerTestThree())); System.out.println(); System.out.printf("%-30s%9d\n", "include one object:", SizeOfObject.sizeOf(new ReferenceTestOne())); System.out.printf("%-30s%9d\n", "include one object:", SizeOfObject.sizeOf(new ReferenceTestTwo())); } public static void main(String[] args) { test2(); } static class IntegerTestOne { private int i1 = 1; } static class IntegerTestTwo { private int i1 = 1; private int i2 = 1; } static class IntegerTestThree { private int i1 = 1; private int i2 = 1; private int i3 = 1; } static class ReferenceTestOne { private Object o1 = new Object(); } static class ReferenceTestTwo { private Object o1 = new Object(); private Object o2 = new Object(); } }
64 位 | -XX:-UseCompressedOops | -XX:+UseCompressedOops |
---|---|---|
Object | 8 + 8 = 16 (对象头+类型指针) | 8 + 4 + 4 = 16(对象头+压缩的类型指针+对齐填充) |
包含一个int | (8 + 8) + 4 + 4 = 24 | (8 + 4) + 4 = 16 |
包含两个int | (8 + 8) + 4*2 = 24 | (8 + 4) + 4*2 + 4 = 24 |
包含三个int | (8 + 8) + 4*3 + 4 = 32 | (8 + 4) + 4*3 = 24 |
不压缩引用占 8 个字节,压缩占 4 个字节 | ||
包含一个引用 | (8 + 8) + 8 = 24 | (8 + 4) + 4 = 16 |
包含两个引用 | (8 + 8) + 8*2 = 32 | (8 + 4) + 4*2 + 4 = 24 |
public class MemoryStaticTest { /** * -javaagent:{jar包路径}\SizeOfObject.jar * 使用指针压缩,在必定状况下64位HotSpot jvm默认指针压缩 * * Output: * amd64 +UseCompressedOops * StaticTest: 16 * Integer: 16 * StaticReferenceTest: 16 * * @param args */ public static void main(String[] args) { System.out.println(System.getProperty("os.arch") + " +UseCompressedOops"); System.out.printf("%-30s%9d\n", "StaticTest:", SizeOfObject.sizeOf(new StaticTest())); System.out.printf("%-30s%9d\n", "Integer:", SizeOfObject.sizeOf(new Integer(1))); System.out.printf("%-30s%9d\n", "StaticReferenceTest:", SizeOfObject.sizeOf(new StaticReferenceTest())); } static class StaticTest { private static int i1 = 1; private static int i2 = 1; private static int i3 = 1; private static int i4 = 1; private static int i5 = 1; private static int i6 = 1; } static class StaticReferenceTest { private static Object o1 = new Object(); private static Object o2 = new Object(); private static Object o3 = new Object(); private static Object o4 = new Object(); private static Object o5 = new Object(); } }
一个引用在 64 位的时候,为何是 8 个字节;32 位的时候,为何是 4 个字节测试
这一切均可以在 jvm 的实现中找到答案,也就是看 C++ 代码。只是我还没到这个阶段=。=ui