Java中对象的内存消耗是多少?
一个具有100个属性的对象所消耗的内存空间是否与100个具有一个属性的对象所消耗的内存空间相同 为一个对象分配了多少内存?Java中对象的内存消耗是多少?,java,memory,footprint,Java,Memory,Footprint,一个具有100个属性的对象所消耗的内存空间是否与100个具有一个属性的对象所消耗的内存空间相同 为一个对象分配了多少内存? 添加属性时使用了多少额外空间?否,注册对象也需要一些内存。具有1个属性的100个对象将占用更多内存。不,100个小对象需要的信息(内存)比一个大对象多。每个对象都有一定的开销用于其关联的监视器和类型信息,以及字段本身。除此之外,几乎可以按照JVM认为合适的方式(我相信)布局字段,但至少有些JVM会非常紧凑地打包。考虑这样一个类: public class SingleByt
添加属性时使用了多少额外空间?否,注册对象也需要一些内存。具有1个属性的100个对象将占用更多内存。不,100个小对象需要的信息(内存)比一个大对象多。每个对象都有一定的开销用于其关联的监视器和类型信息,以及字段本身。除此之外,几乎可以按照JVM认为合适的方式(我相信)布局字段,但至少有些JVM会非常紧凑地打包。考虑这样一个类:
public class SingleByte
{
private byte b;
}
vs
在32位JVM上,我希望100个SingleByte
实例占用1200字节(由于填充/对齐,8字节的开销+4字节的字段)。我希望一个100字节的OneHundredBytes
实例占用108字节的开销,然后压缩100字节。当然,它可能因JVM而异-一个实现可能会决定不将字段打包为OneHundredBytes
,这会导致占用408字节(=8字节开销+4*100对齐/填充字节)。在64位JVM上,开销也可能更大(不确定)
编辑:见下面的评论;显然,热点填充到8字节边界,而不是32字节,因此SingleByte
的每个实例将占用16字节
无论哪种方式,“单个大对象”的效率至少与多个小对象相同——对于这样的简单情况。指出,这不是一个简单的问题:
JVM可以自由地在内部以任何方式存储数据,不管大小,不需要任何填充或开销,尽管原语的行为必须与官方大小相同。例如,JVM或本机编译器可能决定将
布尔[]
存储在64位长的块中,如位集
。它不必告诉你,只要程序给出相同的答案
- 它可能会在堆栈上分配一些临时对象李>
- 它可能会优化一些完全不存在的变量或方法调用,并用常量替换它们李>
- 它可能会对方法或循环进行版本化,即编译一个方法的两个版本,每个版本针对特定情况进行了优化,然后预先决定调用哪个版本李>
-Xmx32G
;32Gb以上的8个字节(-Xmx32G
)。(见附件。)
因此,64位JVM通常需要增加30-50%的堆空间。(,2012,JDK 1.7)
装箱类型、数组和字符串
与基元类型相比,盒装包装器具有开销(从):
:16字节的结果比我预期的稍差,因为Integer
值只能容纳4个额外字节。与可以将值存储为基元类型相比,使用int
会消耗300%的内存开销整数
:16字节也很明显,堆上的实际对象大小取决于特定JVM实现针对特定CPU类型执行的低级内存对齐。看起来Long
是8字节的对象开销,加上8字节的实际Long值。相反,Long
有一个未使用的4字节洞,很可能是因为我使用的JVM强制对象在8字节字边界上对齐Integer
- 多维数组:它提供了另一个惊喜。
开发人员通常在数值和科学计算中使用类似于
的结构 在int[dim1][dim2]
数组实例中,每个嵌套的int[dim1][dim2]
数组本身就是一个int[dim2]
对象。每个都会增加通常的16字节数组开销。当我不需要三角形或参差不齐的数组时,这表示纯开销。当数组维度差异很大时,影响会增大 例如,一个
实例需要3600字节。与int[128][2]
实例使用的1040字节(具有相同的容量)相比,3600字节表示246%的开销。在int[256]
的极端情况下,开销系数几乎为19!与C/C++的情况相比,在C/C++中,相同的语法不会增加任何存储开销字节[256][1]
:字符串的内存增长跟踪其内部字符数组的增长。但是,String
类又增加了24字节的开销 对于大小不超过10个字符的非空字符串
,相对于有效负载(每个字符2个字节加上长度4个字节)增加的开销成本从100%到400%不等字符串
X
的实例将使用17个字节。但是,由于对齐(也称为填充),JVM
public class OneHundredBytes
{
private byte b00, b01, ..., b99;
}
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
}
java.lang.Runtime.getRuntime();
public class PerformanceTest {
private static final long MEGABYTE = 1024L * 1024L;
public static long bytesToMegabytes(long bytes) {
return bytes / MEGABYTE;
}
public static void main(String[] args) {
// I assume you will know how to create an object Person yourself...
List <Person> list = new ArrayList <Person> ();
for (int i = 0; i <= 100_000; i++) {
list.add(new Person("Jim", "Knopf"));
}
// Get the Java runtime
Runtime runtime = Runtime.getRuntime();
// Run the garbage collector
runtime.gc();
// Calculate the used memory
long memory = runtime.totalMemory() - runtime.freeMemory();
System.out.println("Used memory is bytes: " + memory);
System.out.println("Used memory is megabytes: " + bytesToMegabytes(memory));
}
}
Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
java.lang.Integer object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int Integer.value N/A
Instance size: 16 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.util.VMSupport;
public static void main(String[] args) {
System.out.println(VMSupport.vmDetails());
System.out.println(ClassLayout.parseClass(Integer.class).toPrintable());
}
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.3.2</version>
</dependency>