当我在某处读到时,在创建实例并从堆分配空间时分配内存.如果它是正确的,那么在实例和对象创建期间分配了多少内存?
在方法中声明的变量存储在堆栈中,而实际对象存储在堆中.考虑
Integer a = new Integer(10);
Run Code Online (Sandbox Code Playgroud)
在此示例中,在堆上创建Integer类型的对象,并返回引用(32或64位)并将其作为变量"a"存储在方法堆栈中.如果JVM更喜欢优化,JVM可以自由地将这样的变量保存在CPU寄存器中.
使用new关键字时会分配对象的内存.它通常在TLAB(线程本地分配缓冲区)中分配,TLAB是为正在运行的线程保留的eden堆的一部分.从而将对象分配的开销减少到简单的"指针碰撞".不使用TLAB时的两次是1)当对象太大而没有剩余的空间时,在这种情况下它将被直接提升到旧的和2)当支持JVM通过逃逸分析决定它可以避免完全对象并直接分配到堆栈(甚至将对象分开并仅分配堆栈上所需的字段).
保留的内存量包括一个对象头,通常是2个字(数组为3 个字),然后是对象及其父类中声明的每个字段的空格.这些字段的总大小取决于JVM和底层平台(例如32位或64位)和JVM配置(如压缩引用).
------------------+------------------+------------------ +--------------------------
| mark word | klass pointer | array size (opt) | padding and fields |
------------------+------------------+-------------------+--------------------------
Run Code Online (Sandbox Code Playgroud)
询问JVM的大小是不正式的,但EHCache sizeOf是一个非常好的"最佳猜测",它使用不同JVM的知识并通过使用Java Unsafe访问底层指针.
理解每个字段大小的起点是Java语言定义的基元大小,但这只是最小的大小,因为JVM设计用于32位,因此小于此的基元通常被填充到32位.例如布尔人.
字段的确切布局将因JVM而异,但它们将倾向于按照从继承树的根开始定义它们的类进行分组.例如,考虑一下
和
上面的图片来自这篇非常好的博客文章,内容非常清楚地描述了内存布局,
归档时间: |
|
查看次数: |
6498 次 |
最近记录: |