五、JVM之堆内存

堆结构分代图

堆结构分代的意义

  Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代、老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略。
  堆内存是虚拟机管理的内存中最大的一块,也是垃圾回收最频繁的一块区域,我们程序所有的对象实例都存放在堆内存中。给堆内存分代是为了提高对象内存分配和垃圾回收的效率。试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象所花费的时间代价是巨大的,会严重影响我们的GC效率。
  有了内存分代,情况就不同了,新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代中,静态属性、类信息等存放在永久代中,新生代中的对象存活时间短,只需要在新生代区域中频繁进行GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收,永久代中回收效果太差,一般不进行垃圾回收,还可以根据不同年代的特点采用合适的垃圾收集算法。分代收集大大提升了收集效率,这些都是内存分代带来的好处。

堆结构分代

? Java虚拟机将堆内存划分为新生代、老年代和永久代,永久代是HotSpot虚拟机特有的概念(JDK1.8之后为metaspace替代永久代),它采用永久代的方式来实现方法区,其他的虚拟机实现没有这一概念,而且HotSpot也有取消永久代的趋势,在JDK 1.7中HotSpot已经开始了“去永久化”,把原本放在永久代的字符串常量池移出。永久代主要存放常量、类信息、静态变量等数据,与垃圾回收关系不大,新生代和老年代是垃圾回收的主要区域。

新生代(Young Generation)

  新生成的对象优先存放在新生代中,新生代对象朝生夕死,存活率很低,在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高。
  HotSpot将新生代划分为三块,一块较大的Eden(伊甸)空间和两块较小的Survivor(幸存者)空间,默认比例为8:1:1。划分的目的是因为HotSpot采用复制算法来回收新生代,设置这个比例是为了充分利用内存空间,减少浪费。新生成的对象在Eden区分配(大对象除外,大对象直接进入老年代),当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。
  静态版GC开始时,对象只会存在于Eden区,From Survivor区和To Survivor区是空的(作为保留区域)。GC进行时,Eden区中所有存活的对象都会被复制到From Survivor区。若From Survivor区也满了,再对该区进行垃圾回收,然后把所有存货的对象复制到To Survivor区。那如果To Survivor区也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生Major GC(FullGC),进行养老区的内存清理。若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”,通常Full GC 所消耗的性能是Minor GC的十倍以上。

? 动态版首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom区,当Eden区再次触发GC的时候会扫描Eden区和From区,对这两个区进行垃圾回收,经过这次回收后还存活的对象,则直接赋值到To区域(如果有对象的年龄已经达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄加+1。然后,清空Eden和From区中的对象,接着, From Survivor区和To Survivor区会交换它们的角色,也就是新的To Survivor区就是上次GC清空的From Survivor区,新的From Survivor区就是上次GC的To Survivor区,总之,不管怎样都会保证To Survivor区在一轮GC后是空的。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定默认是15),最终如果还是存活,就存入老年代。

老年代(Old Generationn)

? 在新生代中经历了多次(具体看虚拟机配置的阀值)GC后仍然存活下来的对象会进入老年代中。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。

永久代(Permanent Generationn)(JDK1.8后移除)

? 永久代存储类信息、常量、静态变量、即时编译器编译后的代码等数据。

? 永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占用的内存。

元空间(Meta Space)

元空间是JDK 1.8 之后才有的,功能和永久代类似。唯一到的区别是,永久代使用的是JVM的堆内存空间,而元空间使用的是物理内存,直接受到本机的物理内存限制。

因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入native memory,字符串池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不再由MaxPermSize控制,而由系统实际可用空间来控制。

原文地址:https://www.cnblogs.com/lee0527/p/12217540.html

时间: 2024-12-09 00:08:12

五、JVM之堆内存的相关文章

jvm 03-java堆内存模型

java中最大的特点在于其具备良好的垃圾收集特性 GC是整个java之中最重要的安全保证 整个JVM中的GC的处理机制:对不需要的对象进行标记,而后进行清除 JVM堆内存划分 在JDK1.8之后,将最初的永久带内存空间取消了,该图为JDK1.8之前的内存空间组成 取消永久代目的是为了将HotSpot于JRockit两个虚拟机标准联合为一个 在整个JVM堆内存之中实际上将内存分为了三部分: 新生带(年轻代):新对象和没达到一定年龄的对象都在年轻代 老年代:被长时间使用的对象,老年代的内存空间应该要

JVM的堆内存和栈内存中存储的数值或类型的区别在哪里

基本类型变量的值和内容是一致的引用类型变量的值在堆内存,赋值的内容是一个地址,这个地址也在栈内存,指向堆内存引用类型变量的值是内存地址,内存地址在栈内存,指向堆:内容是实例,在堆内存 引用类型变量时,栈内存存储的是指向堆的内存地址,真正数据在堆内存中,栈内存中存的是指向堆的地址,占用8个字节 类里面方法外的是成员方法跟属性(property),如果属性没有static修饰就是在堆,有即为静态属性(类属性)就不在,即在永久区,所有对象公用一份:eg:int i = 4,这个4 在栈内存 ,i是一个

[转]JVM 堆内存设置原理

堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大. Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation).年老代和年轻代的划分对垃圾收集影响比较大. 年轻代 所有新生

jvm堆内存分布及gc发生的条件

jvm虚拟机对内存管理主要体现在堆内存的管理上,我们可以在启动jvm的时候设置jvm对内存大小及调整策略. 1.jvm启动参数: -Xms:jvm启动时初始堆大小. -Xmx:jvm堆的最大值. -Xss:线程栈大小. -Dname=value:jvm全局属性设置. jvm启动参数设置有很多,以上只是列举本人接触过的几个参数. 1)首先,-Xms是jvm启动时堆内存的初始大小,当堆内存不够用时,jvm调整堆大小到-Xmx设置的大小.一般resin这些服务器会把-Xms和-Xmx大小设置一样以避免

jvm堆内存优化详解

在日常的运维工作中用到tomcat,都需要对tomcat中的jvm虚拟机进行优化,只有知道需要优化参数的具体用处,才能深刻体会优化jvm的意义所在. 在平常的工作中我们谈对jvm的优化,主要是针对java的堆内存的优化和垃圾回收机制的优化. JVM堆内存示意图: JVM的堆内存的组成: young generation:新生代 eden:伊甸园区 surived:存活区 其中存活区有2个,第1个为S0,第2个为S1 old generation:老年代 permanent generation:

JVM 堆内存设置原理(转)

堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大. Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation).年老代和年轻代的划分对垃圾收集影响比较大. 年轻代 所有新生

【转】JVM 堆内存设置原理

堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大. Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation).年老代和年轻代的划分对垃圾收集影响比较大. 年轻代 所有新生

堆内存设置以及垃圾回收方式

堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大. Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation).年老代和年轻代的划分对垃圾收集影响比较大. 年轻代 所有新生

堆内存设置

原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定义信息,与垃圾收集器要收集的Java对象关系不大. Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年轻代(Young Generation).年老代和年轻代的划分对垃圾收集影响比较大. 年轻代 所有新生成的对象首先