通常情况下Hotspot虚拟机里Heap(堆)中的Java对象占用的内存包括:
- 基本数据类型的成员变量(primitive field),boolean/byte类型耗用1个字节,char/short类型耗用2个字节,int/float类型耗用4个字节,long/double类型耗用8个字节
- 对象类型的成员变量(reference field),每个变量一个4个字节的reference
于是对象占用的内存大小可以用下面的公式进行估算:
例如,对于下面一个Class:
class MyClass { // 8 bytes (object header) byte a; // 1 byte int c; // 4 bytes boolean d; // 1 byte long e; // 8 bytes Object f; // 4 bytes (reference) }
不考虑padding(对齐)的情况下该类的实例大约占用26(8 + 1 + 4 + 1 + 8 + 4)个字节,进行padding后将占用32个字节的空间。
注意:这里估算的内存占用大小并不包括对象类型的成员变量所占用的内存大小,这里只计算reference占用的内存大小。
一维数组的内存占用量:
在Java里数组也是对象,且数组对象的Object Header比普通对象的要多4个字节,这4个字节是用来存储数组长度用的。另外数组对象也会被Padding(补齐)。
基本数据类型的数组对象占用的内存大小可以用下面的公式进行估算:
如长度为10的int类型的数组int[10]占用的内存大小为: ceil((12 + 4*10)/8)*8 = 56
对象数组Object[]占用的内存大小可以用下面的公式进行估算:
4*m中的4表示每个Object reference占用的内存大小,4个字节;m表示数组的长度。
再例如,对于String类:
public final class String { // 8 bytes (object header) private final char value[]; // 4 bytes (reference) private final int offset; // 4 bytes private final int count; // 4 bytes private int hash; // 4 bytes }
一个包含n个字符的String对象整体(包括char[]数组)占用的内存大小为:
二维数组的内存占用量:
Java中的二维(多维)数组与C语言中的二维(多维)数组有非常大的不同。Java中的二维(多维)数组是由nested数组构成的一个级联结构,二维(多维)数组中的每一行都是一个reference指向的nested数组。
于是对于一个m*n的二维数组array[m][n],它的内存占用量包括下面两部分:
1个长度为m的外层数组占用的内存,可以表示为:ceil((12 + 4*m)/8)*8
m个长度为n的内存数组占用的内存,可以表示为:m*(ceil((12 + sizeof(nested_array_type)*n)/8)*8)
对于基本数据类型的二维数组,sizeof(nested_array_type)为对应基本数据类型的内存使用量
对于Object[][],sizeof(nested_array_type)等于4个字节,即reference的内存使用量
例如,对于int类型的二维数组int[m][n],它的内存占用量估算为:
ceil((12 + 4*m)/8)*8 + m*(ceil((12 + 4*n)/8)*8)
假设(m=1000000, n=3),则该二维数组的内存占用量为:
ceil((12 + 4*1000000)/8)*8 + 1000000*(ceil((12 + 4*3)/8)*8) = 28,000,016
结论:尽量避免长期持有(引用)大规模的二维数组对象
相关推荐
本示例主要探讨如何测试Java对象占用的内存大小,以便更好地理解内存使用情况。 首先,`SizeOf.java`可能是一个实现自定义内存大小计算的类。在Java中,由于垃圾回收机制的存在,直接获取对象的内存占用并不像C++等...
首先,我们需要理解Java对象内存占用的基本原理。每个Java对象都由三部分组成:对象头(Object Header)、实例数据(Instance Data)和对齐填充(Padding)。对象头包含对象引用和类型信息,实例数据是对象实际存储...
当我们谈论“Java对象内存大小”时,我们通常指的是一个Java对象在内存中占据的空间,包括对象头、实例字段以及可能的对齐填充。这个知识点对于开发高效缓存系统尤其重要,因为缓存需要精确管理内存来最大化存储效率...
"java-sizeof-0.0.4"是一个用于分析Java对象内存占用的工具,它可以帮助开发者更好地理解对象在运行时的内存消耗。这个工具提供了查看对象实例大小的能力,这对于调试和性能优化非常有用。"java-sizeof-0.0.4"包含三...
本文将深入探讨如何统计缓存(尤其是Java对象)所占的内存大小,以及这对理解程序内存消耗的重要性。 首先,我们要知道Java对象的内存开销主要由三部分组成:对象头、实例数据和对齐填充。对象头包含对象的类型信息...
本篇文章将深入探讨如何计算Java对象占用的内存字节数,以及影响这一数值的因素。 首先,Java对象在堆内存中由四个部分组成:对象头(A)、基本类型域(B)、引用类型域(C)和填充物(D)。 **对象头(A)**: ...
这篇博客文章可能探讨了如何通过不同的工具和技术来估算Java对象在内存中的占用空间。 首先,Java对象的大小不是固定不变的,它取决于对象的类结构,包括类中的属性数量、类型以及虚拟机的实现。每个对象都会有一个...
这个“Java内存使用系列一Java对象的内存占用”主题旨在深入探讨Java对象在内存中的表现,以及如何有效地管理这些资源。Java开发人员需要理解内存分配、垃圾回收机制以及如何避免内存泄漏,以确保程序的高效运行。 ...
在Java世界中,JVM(Java虚拟机)是运行Java应用程序的关键组件。它负责解析字节码、管理内存以及执行程序。...通过运行这些脚本,我们可以获取更具体的对象内存占用信息,进一步优化我们的Java应用。
总之,Java对象和数组的内存占用取决于JVM的配置、对象的字段、数组的元素类型和长度等因素。开启或关闭压缩选项会影响对象和数组引用的大小,进而影响整体的内存占用。对于内存优化和性能调优来说,了解这些细节至...
例如,对象的内存大小总是8的倍数,这意味着即使一个对象的理论内存大小是41字节,它仍然会占用48字节的内存空间,因为JVM会进行向上对齐。 总结而言,本文档提供了一个深入的分析,帮助读者理解在Java编程中,不同...
堆是 Java 程序员第二常用的存储区域,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java 的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。堆...
在Java编程语言中,了解一个对象的内存大小是很有用的,特别是在性能调优和内存管理方面。`sizeOf`通常是指用来计算对象在内存中占用空间的一种方法。本篇文章将探讨如何通过Java来实现这样的功能,以及相关知识点。...
### Java内存对象分配过程研究 #### 一、引言 Java作为一门强大的面向对象编程语言,在实际开发过程中,对象的创建及其内存管理是至关重要的环节。深入理解对象在内存中的分配过程不仅能够帮助开发者设计出更为...
在Java中,直接获取一个对象所占用的内存大小并非易事。常见的做法是在运行特定代码之前记录当前的内存状态,待代码执行完成后,触发垃圾回收机制,并再次记录内存状态。通过对比两次内存状态的变化,可以估算出代码...
本文介绍了在Java多线程环境下减少内存占用量的一些关键策略,包括线程生命周期管理、对象生命周期设计、同步机制选择、线程池的使用和线程数量控制。同时,代码的异常处理和JVM参数调优也是提升多线程应用性能的...
Java的垃圾回收机制(Garbage Collection, GC)负责自动回收不再使用的对象所占用的堆内存。当一个对象不再有引用指向它时,该对象成为垃圾,GC会在适当的时候将其回收,释放内存。在实验中,虽然没有直接涉及垃圾...
8、程序里不可避免大量使用字符串处理,避免使用 String,应大量使用StringBuffer,每一个 String 对象都得独立占用内存一块区域。 在使用字符串时,应该避免使用 String,而应该使用 StringBuffer,以免内存溢出。...
Java对象的内存布局是Java虚拟机(JVM)中至关重要的一部分,它涉及到对象创建、内存分配以及对象访问等核心概念。在Java程序中,我们通常使用`new`关键字创建对象,但这只是表面操作,背后涉及的内存管理和构造器...
首先,Java对象的大小不仅仅包括其字段的大小,还包括对象头(object header)的大小,对于HotSpot虚拟机,它包含了对齐填充、Mark Word、Klass Pointer等部分。此外,如果对象是数组,还需要考虑数组长度字段。理解...