ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JVM系列(3):堆(Heap)

2019-12-28 21:53:35  阅读:181  来源: 互联网

标签:Java Heap 虚拟机 永久 GC 内存 JVM 系列 常量


介绍


Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

 

堆区组成


  一.Young Generation Space :新生区 Young/New

  二.Tenure generation space :养老区 Old/ Tenure

  三.Permanent Space :永久区 Perm

  一个 JVM 实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行

  堆在逻辑上可以分为三个部分:新生区,养老区,永久区(1.8后叫元空间)

  物理上分为:新生区,养老区

  

新生区 Young/New


 新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:

  伊甸区(Eden space):所有的类都是在伊甸区被 new 出来的。
  幸存者区(Survivor pace):幸存区有两个: 0 区(Survivor 0 space)和 1 区(Survivor 1 space),又叫from 和 to
  当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC,轻GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。若幸存 0 区也满了,再对该区进行垃圾回收,然后移动到 1区。那如果 1 区也满了呢?再移动到养老区

 

养老区  Old/ Tenure


 当对象在新生区经历过多次(默认 15 次)GC 依然幸存则进入养老区。若养老区也满了,那么这个时候将产生MajorGC(FullGC,重GC),进行养老区的内存清理。若养老区执行了 Full GC 之后发现依然无法进行对象的保存,就会产生OOM 异常“OutOfMemoryError”

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

原因有二:
  (1)Java 虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx 来调整。
  (2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

 

永久区  Perm 


 

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

  例如:在一Tomcat 下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致 Perm 区被占满。

Jdk1.6 及之前: 有永久代, 常量池 1.6 在方法区

Jdk1.7:有永久代,但已经逐步“去永久代”,常量池 1.7 在堆

Jdk1.8 及之后: 无永久代,常量池 1.8 在元空间

  实际而言,方法区(Method Area)和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息+普通常量+静态常量+编译器编译后的代码等等,虽然 JVM 规范将方法区描述为堆的一个逻辑部分,但它却还有一个别名叫做 Non-Heap(非堆),目的就是要和堆分开。

  对于 HotSpot 虚拟机,很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” ,但严格本质上说两者不同,或者说使用永久代来实现方法区而已,永久代是方法区(相当于是一个接口 interface)的一个实现,jdk1.7 的版本中,已经将原本放在永久代的字符串常量池移走。常量池(Constant Pool)是方法区的一部分,Class 文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放。

标签:Java,Heap,虚拟机,永久,GC,内存,JVM,系列,常量
来源: https://www.cnblogs.com/steakliu/p/12113164.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有