Java中对象的内存消耗是多少? [英] What is the memory consumption of an object in Java?

查看:124
本文介绍了Java中对象的内存消耗是多少?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个具有100个属性的对象占用的内存空间是否与100个对象相同,每个属性有一个属性?

Is the memory space consumed by one object with 100 attributes the same as that of 100 objects, with one attribute each?

为对象分配了多少内存?$
添加属性需要多少额外空间?

How much memory is allocated for an object?
How much additional space is used when adding an attribute?

推荐答案

Mindprod 指出这不是一个简单的问题要回答:

Mindprod points out that this is not a straightforward question to answer:


JVM可以随意存储数据,无论是内部,大小还是小端,都有任何填充或开销,但原语必须表现得像官方大小一样。

例如,JVM或本机编译器可能决定以64位长块存储 boolean [] ,如 BitSet 。它没有必要告诉你,只要程序给出相同的答案。

A JVM is free to store data any way it pleases internally, big or little endian, with any amount of padding or overhead, though primitives must behave as if they had the official sizes.
For example, the JVM or native compiler might decide to store a boolean[] in 64-bit long chunks like a BitSet. It does not have to tell you, so long as the program gives the same answers.


  • 它可能会在堆栈上分配一些临时对象。

  • 它可以优化一些完全不存在的变量或方法调用,用常量替换它们。

  • 它可以对方法或循环进行版本控制,即编译方法的两个版本,每个版本针对特定情况进行优化,然后预先决定调用哪一个。

当然硬件和操作系统都有多层缓存,片上缓存,SRAM缓存,DRAM缓存,普通RAM工作集和支持磁盘上的存储。您的数据可能在每个缓存级别都是重复的。所有这些复杂性意味着您只能非常粗略地预测RAM消耗。

Then of course the hardware and OS have multilayer caches, on chip-cache, SRAM cache, DRAM cache, ordinary RAM working set and backing store on disk. Your data may be duplicated at every cache level. All this complexity means you can only very roughly predict RAM consumption.



测量方法



您可以使用 Instrumentation.getObjectSize () 获取对象消耗的估计值。

Measurement methods

You can use Instrumentation.getObjectSize() to obtain an estimate of the storage consumed by an object.

可视化实际对象布局,足迹和引用,您可以使用 JOL(Java对象布局)工具

To visualize the actual object layout, footprint, and references, you can use the JOL (Java Object Layout) tool.

在现代64位JDK中,一个对象有一个12字节的标头,填充到8个字节的倍数,因此最小的对象大小是16个字节。对于32位JVM,开销为8个字节,填充为4个字节的倍数。 (来自 Dmitry Spikhalskiy的回答 Jayen的回答,以及 JavaWorld 。)

In a modern 64-bit JDK, an object has a 12-byte header, padded to a multiple of 8 bytes, so the minimum object size is 16 bytes. For 32-bit JVMs, the overhead is 8 bytes, padded to a multiple of 4 bytes. (From Dmitry Spikhalskiy's answer, Jayen's answer, and JavaWorld.)

通常情况下,32位平台或64位平台上的引用为4字节,最高为 -Xmx32G ;和32Gb以上的8个字节( -Xmx32G )。 (请参阅压缩对象参考。)

Typically, references are 4 bytes on 32bit platforms or on 64bit platforms up to -Xmx32G; and 8 bytes above 32Gb (-Xmx32G). (See compressed object references.)

因此,64位JVM通常需要30-50%的堆空间。 我应该使用32位还是64位JVM?,2012,JDK 1.7)

As a result, a 64-bit JVM would typically require 30-50% more heap space. (Should I use a 32- or a 64-bit JVM?, 2012, JDK 1.7)

与原始类型相比,盒装包装器有开销(来自 JavaWorld ):

Boxed wrappers have overhead compared to primitive types (from JavaWorld):



  • 整数 :16字节的结果比我预期的要差一些,因为 int 值可以适合4个额外字节。与我将值存储为基本类型时相比,使用 Integer 花费了300%的内存开销

  • Integer: The 16-byte result is a little worse than I expected because an int value can fit into just 4 extra bytes. Using an Integer costs me a 300 percent memory overhead compared to when I can store the value as a primitive type

Long :16字节:显然,堆上的实际对象大小受特定JVM完成的低级内存对齐的影响特定CPU类型的实现。看起来像 Long 是8字节的对象开销,再加上实际长值的8字节。相比之下, Integer 有一个未使用的4字节漏洞,很可能是因为我使用的JVM强​​制在8字节字边界上对象对齐。

Long: 16 bytes also: Clearly, actual object size on the heap is subject to low-level memory alignment done by a particular JVM implementation for a particular CPU type. It looks like a Long is 8 bytes of Object overhead, plus 8 bytes more for the actual long value. In contrast, Integer had an unused 4-byte hole, most likely because the JVM I use forces object alignment on an 8-byte word boundary.

其他容器也很昂贵:



  • 多维数组:它提供了另一个惊喜。

    开发人员通常使用类似的结构数学和科学计算中的 int [dim1] [dim2]

  • Multidimensional arrays: it offers another surprise.
    Developers commonly employ constructs like int[dim1][dim2] in numerical and scientific computing.

int中[dim1] [dim2] 数组实例,每个嵌套的 int [dim2] 数组都是对象凭借自己的权利。每个都添加了通常的16字节数组开销。当我不需要三角形或粗糙的数组时,这表示纯粹的开销。当数组维度大不相同时,影响会增大。

In an int[dim1][dim2] array instance, every nested int[dim2] array is an Object in its own right. Each adds the usual 16-byte array overhead. When I don't need a triangular or ragged array, that represents pure overhead. The impact grows when array dimensions greatly differ.

例如, int [128] [2] 实例需要3,600个字节。与1,040字节相比, int [256] 实例使用(具有相同的容量),3,600字节代表246%的开销。在 byte [256] [1] 的极端情况下,开销因子几乎为19!将其与C / C ++情况相比较,在该情况下,相同的语法不会增加任何存储开销。

For example, a int[128][2] instance takes 3,600 bytes. Compared to the 1,040 bytes an int[256] instance uses (which has the same capacity), 3,600 bytes represent a 246 percent overhead. In the extreme case of byte[256][1], the overhead factor is almost 19! Compare that to the C/C++ situation in which the same syntax does not add any storage overhead.

String :a String 的内存增长跟踪其内部char数组的增长。但是, String 类会增加另外24个字节的开销。

String: a String's memory growth tracks its internal char array's growth. However, the String class adds another 24 bytes of overhead.

对于非空字符串大小为10个字符或更少的,相对于有用的有效负载增加的开销成本(每个字符2个字节加上4个字节的长度),范围从100到400%。

For a nonempty String of size 10 characters or less, the added overhead cost relative to useful payload (2 bytes for each char plus 4 bytes for the length), ranges from 100 to 400 percent.



对齐



考虑这个示例对象

class X {                      // 8 bytes for reference to the class definition
   int a;                      // 4 bytes
   byte b;                     // 1 byte
   Integer c = new Integer();  // 4 bytes for a reference
}

一个天真的总和会暗示一个实例 X 将使用17个字节。但是,由于对齐(也称为填充),JVM以8个字节的倍数分配内存,因此它将分配24个字节而不是17个字节。

A naïve sum would suggest that an instance of X would use 17 bytes. However, due to alignment (also called padding), the JVM allocates the memory in multiples of 8 bytes, so instead of 17 bytes it would allocate 24 bytes.

这篇关于Java中对象的内存消耗是多少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆