Java虚拟机(JVM)-- 堆(Heap)

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java虚拟机(JVM)-- 堆(Heap)相关的知识,希望对你有一定的参考价值。

1. 堆(Heap)



1.1 新生区

  • 新生区是类诞生,成长,消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。
  • 新生区又分为两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是在伊甸区被new出来的,幸存区有两个:0区 和 1区,当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC)。将伊甸园中的剩余对象移动到幸存0区,若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区,那如果1区也满了呢?(这里幸存0区和1区是一个互相交替的过程)再移动到养老区,若养老区也满了,那么这个时候将产生MajorGC(Full GC),进行养老区的内存清理,若养老区执行了Full GC后发现依然无法进行对象的保存,就会产生OOM异常 “OutOfMemoryError ”。

如果出现 java.lang.OutOfMemoryError:java heap space异常,说明Java虚拟机的堆内存不够,原因如下:

1、Java虚拟机的堆内存设置不够,可以通过参数 -Xms(初始值大小),-Xmx(最大大小)来调整。
2、代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)或者死循环


1.2 Sun HotSpot(JVM的一种)内存管理

  • 分代管理,不同的区域使用不同的算法:
  • 经过研究,不同对象的生命周期不同,在Java中大部分对象都是临时对象。

1.3 永久区(Perm)

  • 永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。
  • 如果出现 java.lang.OutOfMemoryError:PermGen space,说明是 Java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包,例如:在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致Perm区被占满。

注意:

  • 实际而言,方法区(Method Area)和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码,虽然JVM规范将方法区描述为堆的一个逻辑部分,但它却还有一个别名,叫做Non-Heap(非堆),目的就是要和堆分开。
  • 对于HotSpot虚拟机,很多开发者习惯将方法区称之为 “永久代(Parmanent Gen)”,但严格本质上说两者不同,或者说使用永久代实现方法区而已,永久代是方法区(相当于是一个接口interface)的一个实现,Jdk1.7的版本中,已经将原本放在永久代的字符串常量池移走。
  • 常量池(Constant Pool)是方法区的一部分,Class文件除了有类的版本,字段,方法,接口描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放!



以上是关于Java虚拟机(JVM)-- 堆(Heap)的主要内容,如果未能解决你的问题,请参考以下文章

JVM系列:堆(Heap)

深入Java虚拟机中的Stack和Heap

Java虚拟机的内存组成以及堆内存介绍

20210520 使用jmap分析虚拟机内存状况

20210520 使用jmap分析虚拟机内存状况

Java堆内存Heap与非堆内存Non-Heap