堆
1. 简介
一般Java程序中堆内存是空间最大的一块内存区域。创建出来的对象都存在于堆上。栈上的局部变量表中,可以存放堆上对象的引用。静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间共享。
2. 堆大小组成
堆空间有三个需要关注的值,used total max。
used指的是当前已使用的堆内存,total是java虚拟机已经分配的可用堆内存,max是java虚拟机可以分配的最大堆内存。
使用arths的dashboard -i 刷新毫秒数
命令或者memory
查看: 可以看到已经使用的堆内存是63M,总共的堆内存是110M,如果100M用完了还可以找JVM申请的内存就是118M(228M-110M)
随着堆中的对象增多,当total可以使用的内存即将不足时,java虚拟机会继续分配内存给堆。如果堆内存不足,java虚拟机就会不断的分配内存,total值会变大。total最多只能与max相等。
2.1 模拟堆溢出
public class Jvm03 extends ClassLoader {
public static void main(String[] args) {
int count = 1;
ArrayList<Object> list = new ArrayList();
while (true) {
// 一次往JVM的堆空间添加100M内容
byte[] bytes = new byte[1024 * 1024 * 100];
list.add(bytes);
System.out.println(++count);
}
}
}
执行后报错:
是不是当used = max = total的时候,堆内存就溢出了呢?
不是,堆内存溢出的判断条件比较复杂,在下一章《垃圾回收器》中会详细介绍。
3. 设置堆大小
如果不设置任何的虚拟机参数,max默认是系统内存的1/4,total默认是系统内存的1/64。在实际应用中一般都需要设置total和max的值。
要修改堆的大小,可以使用虚拟机参数–Xmx
(max最大值)和-Xms
(初始的total)。
语法:-Xmx值 -Xms值
单位:字节(默认,必须是1024的倍数)、k或者K(KB)、m或者M(MB)、g或者G(GB)
限制:Xmx必须大于2MB,Xms必须大于1MB
3.1 手动设置堆大小
为何arthas显示的不是1024M呢?
arthas中的heap堆内存使用了JMX技术中内存获取方式,这种方式与垃圾回收器有关,计算的是可以分配对象的内存,而不是整个内存。
Java服务端程序开发时,建议将-Xmx
和-Xms
设置为相同的值,这样在程序启动之后可使用的总内存就是最大内存,而无需向java虚拟机再次申请,减少了申请并分配内存时间上的开销,同时也不会出现内存过剩之后堆收缩的情况。-Xmx
具体设置的值与实际的应用程序运行环境有关,在《实战篇》中会给出设置方案。