什么时候会用到堆内存


通过new关键字创建的对象都会使用堆内存。


概念


对于java应用程序来讲,堆是jvm所管理的内存中最大的一块。是被所有线程共享的一块区域,并在虚拟机启动时创建。此区域的唯一目的就是存放对象实例,java程序里“几乎”所有的对象实例都会在这里创建并分配内存。

jvm规范中对堆的描述是“所有的对象实例以及数组都应当在堆上分配

jvm规范中规定:堆可以处于物理上不连续的内存空间中,但在逻辑上它应该 被视为连续的,这点就像我们用磁盘空间去存储文件一样,并不要求每个文件都连续存放。

堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩 展来实现的(通过参数 -Xmx-Xms 设定)。假如堆中没有内存完成实例分配了,并且也无法进行扩展时 jvm 就会抛出 OutOfMemoryError 异常。


特点


1. 是线程共享的,所以堆中对象都需要考虑线程的安全问题。
2. 有垃圾回收机制
3. 会内存溢出


堆内存溢出


虽然有垃圾回收机制,当对象不会再被使用时就会被当作垃圾回收释放掉。

但是对象不断被产生并且任然有在使用时,这个时候这些对象并不会被当作垃圾回收掉,当对象达到一定的数量时就会使得堆内存被耗尽,从而产生堆内存溢出问题。


例子

public static void main(String[] args){
int i = 0;
try{
List<String> stringList = new ArrayList<>();
String a = "hello";
while(true){
stringList.add(a);
a = a + a;
i++;
}
}catch(Throwable a){
e.printStackTrace();
Sytem.out.println(i);
}
}

在运行这个例子的时候我把堆内存设置成了 8M -Xmx8m ,从而能更快的让jvm抛出溢出信息。

#yyds干货盘点# jvm——堆_内存溢出

运行以上例子抛出了内存溢出的信息:java.lang.OutOfMemoryError:Java heap space

前面是内存溢出的错误信息,后面 Java heap space 翻译过来是 Java 堆空间,才是定位具体是不是堆内存溢出信息。

#yyds干货盘点# jvm——堆_堆内存_02

这个例子就是对象一直被引用不断被插入信息使得 stringList 大小超出了堆内存的大小。