一. 定义
-
Java 虚拟机具有一个在所有 Java 虚拟机线程之间共享的堆。堆是运行时数据区域,从中为所有类实例和数组分配内存。
-
堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为垃圾回收器)回收;对象从不显式解除分配。Java 虚拟机假定没有特定类型的自动存储管理系统,可以根据实施者的系统要求选择存储管理技术。堆可以是固定大小的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可能会收缩堆。堆的内存不需要是连续的。
-
Java 虚拟机实现可以为程序员或用户提供对堆的初始大小的控制,以及如果堆可以动态扩展或收缩,则可以控制最大和最小堆大小。
以下异常情况与堆相关联:
如果计算需要的堆数超过自动存储管理系统所能提供的堆数,则 Java 虚拟机会抛出一个 OutOfMemoryError
Heap堆
- 通过
new
关键字,创建对象都会使用堆内存
二. 特点
- 它是
线程共享
的,堆中对象都需要考虑线程安全的问题
有垃圾回收机制
是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行
垃圾收集的最重要的内存区域。由于现代 VM 采用分代收集算法, 因此 Java 堆从 GC 的角度还可以
细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。
三. 堆内存溢出
演示示例
package jvm1;
import java.util.ArrayList;
import java.util.List;
//java.lang.OutOfMemoryError: Overflow: String length out of range
public class Demo4 {
public static void main(String[] args) {
int i=0;
try {
List<Object> list = new ArrayList<>();
String a="hello";
while(true) {
list.add(a);
a=a+a;
i++;
}
}catch (Throwable e) {
e.printStackTrace();
System.out.println(i);
}
}
}
四. 堆内存诊断
- jps工具
- 查看当前系统中有哪些java进程
- jmap工具
- 查看堆内存占用情况,jmap - heap 进程id
- jconsole工具
- 图形界面的,多功能的监测工具,可以连续监测
jvisualvm
工具
案例:垃圾回收后,内存占用仍然很高
测试代码:
package jvm1;
import java.util.ArrayList;
import java.util.List;
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
List<Student> students = new ArrayList<Student>();
for (int i=0;i<200;i++){
students.add(new Student());
}
Thread.sleep(1000000000L);
}
}
class Student {
private byte[] big=new byte[1024*1024];
}