具有100个属性的一个对象所消耗的存储空间是否与每个具有一个属性的100个对象所消耗的存储空间相同?
为一个对象分配多少内存?
添加属性时会使用多少额外空间?
Mindprod
指出,这不是一个容易回答的简单问题:
JVM可以自由地以内部或大端或小端的任何方式存储数据,并具有一定的填充或开销,尽管基元必须表现得好像它们具有官方大小一样。
例如,JVM或本机编译器可能会决定将boolean[]
64位长块(如)存储为BitSet
。只要程序给出相同的答案,就不必告诉你。
Measurement methods
你可以Instrumentation.getObjectSize()
用来获取对象消耗的存储空间的估计值。
要可视化实际的对象布局,覆盖区和引用,可以使用JOL(Java对象布局)工具。
Object headers and Object references
在现代的64位JDK中,对象具有12个字节的标头,填充为8个字节的倍数,因此最小对象大小为16个字节。对于32位JVM,开销为8字节,填充为4字节的倍数。 (从梅德Spikhalskiy的回答,Jayen的回答,和JavaWorld的。)
通常,引用在32位平台或64位平台(不超过-Xmx32G;)上为4个字节。和32Gb(-Xmx32G)以上的8个字节。 (请参阅压缩的对象引用。)
结果,一个64位JVM通常需要30-50%以上的堆空间。(我应该使用32位还是64位JVM?,2012,JDK 1.7)
Boxed types, arrays, and strings
与原始类型(来自JavaWorld)相比,盒装包装具有额外的开销:
Integer
:16字节的结果比我预期的要差一些,因为一个int
值只能容纳4个额外的字节。Integer
与将值存储为原始类型时相比,使用该方法花了我300%的内存开销
Long
:也为16个字节:显然,堆上的实际对象大小受特定JVM实现针对特定CPU类型的低级内存对齐的约束。看起来Long
是8个字节的对象开销,再加上8个字节的实际long值。相反,Integer
有一个未使用的4字节漏洞,这很可能是因为我使用的JVM在8字节字边界上强制了对象对齐。
其他容器也很昂贵:
Multidimensional arrays
:它提供了另一个惊喜。int[dim1][dim2]
数字和科学计算中的构造。在int[dim1][dim2]
数组实例中,每个嵌套int[dim2]
数组都是Object
独立的。每一个都增加了通常的16字节数组开销。当我不需要三角形或参差不齐的数组时,这表示纯开销。当阵列尺寸大大不同时,影响会增大。
例如,一个int[128][2]
实例占用3,600字节。与int[256]
实例使用的1,040字节(具有相同的容量)相比,3,600字节代表246%的开销。在的极端情况下byte[256][1]
,开销因子几乎为19!将其与C / C ++
情况进行比较,在这种情况下,相同的语法不会增加任何存储开销。
String
:String
的内存增长跟踪其内部char数组的增长。但是,String该类又增加了24个字节的开销。对于String
大小为10个字符或更少的非空字符,相对于有用的有效负载而言,增加的开销成本(每个字符2个字节,长度4个字节)相对于100%到400%。
Alignment
考虑以下示例对象:
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字节。
我有一个非常简单的Web服务器类(基于JavaSE的类)。 当我使用此命令启动编译后的类以限制内存使用时:
问题内容: 我在HP Proliant服务器上运行了高度并发的应用程序。该应用程序是我用erlang编码的文件系统索引器。它在文件系统上找到的每个文件夹中产生一个进程,并将所有文件路径记录在碎片化的Mnesia数据库中。(数据库由表的类型组成,其文件系统的屏幕快照可在 此处 查看。) 下面显示了完成文件系统的高强度工作的代码片段: 该函数是通用的,它需要两个。一个乐趣:与最热门目录一起使用,找到的
问题内容: 我试图检查Go如何处理100,000个goroutine。我写了一个简单的程序来产生许多例程,除了打印一些公告外什么也不做。我将MaxStack大小限制为只有512个字节。但是我注意到程序的大小并没有因此而减少。它消耗了大约460 MB的内存,因此每个goroutine消耗了大约4 KB的内存。我的问题是,我们可以将goroutine的最大堆栈大小设置为低于“最小”堆栈大小(可能为4
我在spring boot中创建了一些服务,我有11个fat jars,我将它们部署在docker容器中,我怀疑每个jar在没有任何使用的情况下消耗了1到1.5 GB的RAM,我通过运行以下命令来检查RAM: 起初我以为是java容器,我试图改成一个使用alpine的容器,但没有任何变化,所以我认为唯一的问题是我的罐子。有没有办法更改罐子正在使用的 RAM?或者这种行为是正常的,因为每个罐子都有一
问题内容: 我需要监视应用程序产生的线程消耗的内存量。如果贪婪的线程消耗太多内存,则想法是采取纠正措施。我已提到Java线程占用多少内存?。关于该链接的建议之一是在我尝试以下工作时使用。 我在四个线程上运行了很长时间。尽管作业不会连续地累积内存,但是所返回的值会不断增加,甚至不会下降。这意味着不会返回线程使用的堆上的实际内存量。它返回自线程启动以来在堆上为线程分配的内存总量。我的平台详细信息如下:
我需要监控应用程序生成的线程所消耗的内存量。如果贪婪的线程占用了太多内存,那么我们可以采取纠正措施。我提到了我的java线程需要多少内存?。关于该链接的建议之一是在ThreadMXBean中使用getThreadAllocatedBytes 我用以下作业试验了getThreadAllocatedBytes。 我在四个线程上运行了相当长的时间。虽然作业不会连续累积内存,但getThreadAlloc