我们讨论的是java heap中对象所占内存。
1.基本类型内存占用
类型 | 占用字节数 |
boolean | 1 |
byte | 1 |
char | 2 |
short | 2 |
int | 4 |
float | 4 |
long | 8 |
double | 8 |
2.对象所占内存由以下部分组成
- object header, 8 byte
- 基本类型,见第1节的表格
- 引用类型,都为4 byte
- padding,如果最后加起来结果不是8的整数倍,要补足到8的整数倍。
举例:
例1)一个空Object占8 byte
例2)
- class A {
- byte a;
- int b;
- boolean c;
- long d;
- Object e;
- }
class A {
byte a;
int b;
boolean c;
long d;
Object e;
}
8 (object header)
+ 1 (a)
+ 4 (b)
+ 1 (c)
+ 8 (d)
+ 4 (e) (引用类型)
= 26
然后要补足到8的倍数,所以结果是32 byte
3.数组
数组是一个特殊的对象,object header需要12 byte,额外的4 byte记录数组的长度)
3.1 一维数组
例3) int[10]
12 (object header)
+ 10 * 4
= 52
然后要补足到8的倍数,所以结果是56
3.2 二维数组
例4) int[10][10]
不可以想当然的认为是10*10*4=400
二维数组是数组的数组,所以这个对象其实只有10个元素,然后每个元素里面都有各自的10个元素
首先计算外围的元素
12+10*4 (注意此处的4只是引用,不是真实的int)=52->56
然后计算里面的元素
每个元素都是一个数组,所以都需要12 byte的header,再加真实的int占用
12+10*4 (注意此处的4计算的是int)=52->56 *10=560
结果=560+56=616
3.3 多维数组
可按二维数组计算方式递归计算
4.工具
可以用classmexer来计算内存使用量
4.1 在上述页面下载classmexer0.0.3
4.2 写一段代码测试
- package memory;
- import com.javamex.classmexer.MemoryUtil;
- class A {
- byte a;
- int b;
- boolean c;
- long d;
- Object e;
- }
- //-javaagent:classmexer.jar
- public class ClassMexerTest {
- public static void main(String[] args) {
- A a = new A();
- long byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(a);
- System.out.println("MemoryUsage of A =" + byteArrayMemoryUsage);
- int[] i1 = new int[10];
- byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(i1);
- System.out.println("MemoryUsage of int[10] =" + byteArrayMemoryUsage);
- int[][] i2 = new int[10][10];
- byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(i2);
- System.out.println("MemoryUsage of int[10][10] =" + byteArrayMemoryUsage);
- }
- }
package memory;
import com.javamex.classmexer.MemoryUtil;
class A {
byte a;
int b;
boolean c;
long d;
Object e;
}
//-javaagent:classmexer.jar
public class ClassMexerTest {
public static void main(String[] args) {
A a = new A();
long byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(a);
System.out.println("MemoryUsage of A =" + byteArrayMemoryUsage);
int[] i1 = new int[10];
byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(i1);
System.out.println("MemoryUsage of int[10] =" + byteArrayMemoryUsage);
int[][] i2 = new int[10][10];
byteArrayMemoryUsage = MemoryUtil.deepMemoryUsageOf(i2);
System.out.println("MemoryUsage of int[10][10] =" + byteArrayMemoryUsage);
}
}
4.3 编译时加入下载好的classmexer.jar即可,
运行时要加入JVM参数 -javaagent:./lib/classmexer.jar (我把jar放在工程根目录下的lib目录里了)
4.4 运行结果
MemoryUsage of A =32
MemoryUsage of int[10] =56
MemoryUsage of int[10][10] =616
验证了上面的理论。
4.5 常见错误
如果出现以下错误,多半是因为找不到那个jar包,请仔细核对jar包路径和指定的-javaagent参数有没有匹配。
- Error occurred during initialization of VM
- agent library failed to init: instrument
- Error opening zip file or JAR manifest missing : lib/classmexer.jar
Error occurred during initialization of VM
agent library failed to init: instrument
Error opening zip file or JAR manifest missing : lib/classmexer.jar
http://xpenxpen.iteye.com/blog/2029879