gpt4 book ai didi

java - 准确测量物体尺寸

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:18:13 24 4
gpt4 key购买 nike

这个问题底部的代码有点长,但基本上创建了一些对象并确定了它们在内存中的大小。我使用以下 JVM 参数执行代码(TLAB 以避免 block 内存分配并据称获得准确的内存使用数据):

-server -Xms2000m -Xmx2000m -verbose:gc -XX:-UseTLAB

我在 64 位 Hotspot JVM 上运行代码并获得以下输出:

Java HotSpot(TM) 64-Bit Server VM
Object: 16 bytes

Object with 1 int: 16 bytes
Object with 2 ints: 24 bytes
Object with 3 ints: 24 bytes

Object with 1 long: 24 bytes
Object with 2 longs: 32 bytes
Object with 3 longs: 40 bytes

Object with 1 reference: 16 bytes
Object with 2 references: 24 bytes
Object with 3 references: 24 bytes

我的结论是:

  • 一个对象占用 12 个字节,对齐到 16 个字节。
  • 一个 int 需要 4 个字节(1 个对象有一个 int 是 12 + 4 = 仍然是 16 个字节,有 2 个 int:12 + 8 = 20 对齐到 24 个字节)
  • 一个long占8个字节(1个long的对象是12 + 8 = 20个字节,对齐到24个字节)

但我很难理解为什么引用使用的空间不如long

由于在 64 位 JVM 上引用是 8 个字节,显而易见的结论是测量方法存在缺陷*。您能解释一下发生了什么以及可以采取什么措施来解决它吗?

*备注:
- 测量期间没有 GC 运行。
- 使用 Netbeans 分析器会产生类似的结果。

public class TestMemoryReference {

private static final int SIZE = 100_000;
private static Runnable r;
private static Object o = new Object();
private static Object o1 = new Object();
private static Object o2 = new Object();
private static Object o3 = new Object();

public static class ObjectWith1Int { int i; }
public static class ObjectWith2Ints { int i, j; }
public static class ObjectWith3Ints { int i, j, k; }
public static class ObjectWith1Long { long i; }
public static class ObjectWith2Longs { long i, j; }
public static class ObjectWith3Longs { long i, j, k; }
public static class ObjectWith1Object { Object o = o1; }
public static class ObjectWith2Objects { Object o = o1; Object p = o2; }
public static class ObjectWith3Objects { Object o = o1; Object p = o2; Object q = o3; }

private static void test(Runnable r, String name, int numberOfObjects) {
long mem = Runtime.getRuntime().freeMemory();
r.run();
System.out.println(name + ":" + (mem - Runtime.getRuntime().freeMemory()) / numberOfObjects + " bytes ");
}

public static void main(String[] args) throws Exception {
System.out.println(System.getProperty("java.vm.name") + " ");

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new Object(); } };
test(r, "Object", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Int(); } };
test(r, "Object with 1 int", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Ints(); } };
test(r, "Object with 2 ints", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Ints(); } };
test(r, "Object with 3 ints", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Long(); } };
test(r, "Object with 1 long", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Longs(); } };
test(r, "Object with 2 longs", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Longs(); } };
test(r, "Object with 3 longs", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith1Object(); } };
test(r, "Object with 1 reference", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith2Objects(); } };
test(r, "Object with 2 references", SIZE);

r = new Runnable() { public void run() { for (int i = 0; i < SIZE; i++) o = new ObjectWith3Objects(); } };
test(r, "Object with 3 references", SIZE);
}
}

最佳答案

Since references are 8 bytes on a 64-bit JVM

这是您可能存在缺陷的假设。

HotSpot 可以使用 "compressed oops"在 JVM 的一些地方使用 32 位值作为引用(强调我的):

Which oops are compressed?

In an ILP32-mode JVM, or if the UseCompressedOops flag is turned off in LP64 mode, all oops are the native machine word size.

If UseCompressedOops is true, the following oops in the heap will be compressed:

  • the klass field of every object
  • every oop instance field
  • every element of an oop array (objArray)

怀疑这就是你的情况。

使用测试

-XX:-UseCompressedOops

-XX:+UseCompressedOops

在我的机器上,默认情况下我得到与你相同的结果,但是使用 -XX:-UseCompressedOops 我看到:

Object:16 bytes
Object with 1 int:24 bytes
Object with 2 ints:24 bytes
Object with 3 ints:32 bytes
Object with 1 long:24 bytes
Object with 2 longs:32 bytes
Object with 3 longs:40 bytes
Object with 1 reference:24 bytes
Object with 2 references:32 bytes
Object with 3 references:40 bytes

...这可能更接近您的预期:)

关于java - 准确测量物体尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14981127/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com