【问题标题】:Where array of primitives stored in JVM memory原语数组存储在 JVM 内存中的位置
【发布时间】:2015-06-15 05:01:34
【问题描述】:

JVM内存分为: 1.方法区 2.堆区 3. 堆栈 4.电脑注册 5. 原生栈

  1. 现在假设我有一个类,其属性为“int[] dealCodes”(int 基元数组)。根据内存管理,一旦交易代码被初始化,内存中就会有(total_elements * 4 字节)的连续内存分配。因此如果数组大小为 10,那么 JVM 内存中将分配 40 个字节。

    我的问题是这 40 个字节将分配在哪个区域(堆或堆栈)?

    我对数组的理解是:它就像任何其他对象一样,位于堆区域下,但不知道数组指向的原语。

  2. 还想了解当数组包含引用时的类似情况(例如,Employees 类型的数组)。我认为在这种情况下,一切都将在堆区。由于这些是引用,因此数组将为每个引用(3​​2 位系统)保存 4 个字节,并且这些引用将指向不同大小的对象。 数组内存分配将根据参考大小而不是对象大小来计算。

请帮我弄清楚以上 2 点。

【问题讨论】:

  • 数组是对象,所以它在堆上

标签: java memory jvm


【解决方案1】:

对象总是堆分配的,所以你的dealCodes 将是 仅在此处分配,但分配的总内存超过 40 字节。

12 bytes (Header) + 4 bytes (Length of Array) + 40 bytes (4 bytes * 10 ints) = 56 bytes

同样的事情也适用于 Employee 对象的数组,除了每个数组元素现在是对 Employee 对象的引用,因此雇员数组占用的 Shallow Heap 仍然是 56 个字节,而 Retained Heap 取决于每个 Employee 对象的大小。

您可以使用 JDK_HOME/bin 目录中的VisualVM 对您的程序/应用程序进行快照,查看每个对象占用的内存,包括浅堆和保留堆大小。

【讨论】:

  • Arkantos 和 Clément...感谢你们两位澄清了我的疑问...清晰的解释.... :-)
【解决方案2】:
  1. 我的问题是这 40 个字节将分配在哪个区域(堆或堆栈)?

已分配堆。

请注意,由于 Object 标头 + 数组的长度属性存在一些开销,因此将分配超过 40 个字节。

如果你对此感兴趣,可以和Java Object Layout一起玩

还想了解当数组包含引用时的类似情况(例如,Employees 类型的数组)。我认为在这种情况下,一切都将在堆区。由于这些是引用,因此数组将为每个引用(3​​2 位系统)保存 4 个字节,并且这些引用将指向不同大小的对象。

没错。

引用的大小取决于架构、32 位和 64 位以及CompressedOops 的可能用法。

【讨论】:

  • 从 JDK7 开始,CompressedOops 默认开启,它们只适用于小于 32 GB 的堆,需要注意:)
  • 是的,它在大多数情况下默认启用,但内存占用仍然取决于 CompressedOops 的使用情况:)
  • 没错,在 Java 6 之前,该标志实际上有助于减少 64 位 JVM 中的对象标头大小,但现在(Java 7 和 8)只要我们在 64 位 VM 上的 32GB 限制:)
  • Arkantos 和 Clément...感谢你们两位澄清了我的疑问...清晰的解释.... :-)
猜你喜欢
  • 2021-01-17
  • 2015-06-13
  • 1970-01-01
  • 2019-08-13
  • 2017-04-18
  • 1970-01-01
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多