java - 在实例创建或使用 new 关键字创建对象期间何时分配内存?

标签 java memory-management

正如我在某处读到的那样,创建实例时会分配内存并从堆中分配空间。如果它是正确的,那么在实例和对象创建期间分配内存的时间和数量是多少?

最佳答案

方法中声明的变量存储在栈中,而实际对象存储在堆中。考虑

Integer a = new Integer(10);

在此示例中,在堆上创建了一个 Integer 类型的对象,并返回一个引用(3​​2 位或 64 位)并将其作为变量“a”存储在方法堆栈中。如果 JVM 喜欢优化,它可以自由地将这样的变量保存在 CPU 寄存器中。

当使用 new 关键字时,对象的内存被分配。它通常在 TLAB 内分配。 (线程本地分配缓冲区)是 eden heap 的一部分保留给正在运行的线程。从而将对象分配的开销减少为简单的“指针碰撞”。不使用 TLAB 的两种情况是 1) 当对象对于剩余空间来说太大时,在这种情况下它将直接提升到 old gen。和 2) 当支持的 JVM 通过 escape analysis 决定时它可以完全避免对象并直接分配到堆栈上(或者甚至将对象分开并仅分配堆栈上所需的字段)。

保留的内存量由对象头组成,通常为 2 words (数组为 3),然后是对象及其父类中声明的每个字段的空间。这些字段的总大小取决于 JVM 和底层平台(例如 32 位或 64 位)以及压缩引用等 JVM 配置。

------------------+------------------+------------------ +--------------------------
|   mark word     |   klass pointer  |  array size (opt) |    padding and fields   |
------------------+------------------+-------------------+--------------------------

官方不支持向 JVM 询问大小,但是 EHCache sizeOf是一个非常好的“最佳猜测”,它使用不同 JVM 的知识并通过使用 Java Unsafe 访问底层指针。 .

了解每个字段大小的起点是 size of primitives defined by the Java language ,但是这只是最小大小,因为 JVM 设计为使用 32 位,因此小于此的原语通常被填充为 32 位。例如 boolean 值。

字段的确切布局会因 JVM 的不同而有所不同,但它们往往会按照定义它们的类从继承树的根开始进行分组。例如,考虑

enter image description here

enter image description here

上面的图片都来自这个很好的blog post很好地描述了内存布局,

关于java - 在实例创建或使用 new 关键字创建对象期间何时分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25055375/

相关文章:

c++ - 内存泄漏/管理建议(方法中的新数组)(c++)

java - 有纹理的三角形,仅渲染一种颜色

java - Java 的 MEF (.NET) 模拟

android - 缓存目录不存在

c - 在堆中分配 C 中的二维数组(不是指针数组)

iphone - 在 objective-C (iphone) 中,如何管理 '@protocol' 引用的内存?

objective-c - OS X如何申请 "clean"内存?

java - 使用字典中没有共同字母的成对单词,找到一对最大化单词长度总和的单词

java - 如何从服务器读取文本文件并在 index.jsp 中显示文本

java - 如何配置 JAX-WS 使用的 XML 解析器的行为