什么是堆内存划分
 
  Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,
  一般分为新生代、老年代和永久代,这就是JVM的内存分代策略。(JDK 1.8之后将最初的永久代取消了,由元空间取代)
 
 
 
为什么要分代?
 
       堆内存是虚拟机管理的内存中最大的一块,也是垃圾回收最频繁的一块区域,我们程序所有的对象实例都存放在堆内存中。给堆内存分代是为了提高对象内存分配和垃圾回收的效率。试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象所花费的时间代价是巨大的,会严重影响我们的GC效率,这简直太可怕了。
       有了内存分代,情况就不同了,新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代中,静态属性、类信息等存放在永久代中,新生代中的对象存活时间短,只需要在新生代区域中频繁进行GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收,永久代中回收效果太差,一般不进行垃圾回收,还可以根据不同年代的特点采用合适的垃圾收集算法。分代收集大大提升了收集效率,这些都是内存分代带来的好处
 
如何进行内存分代划分
        
       Java虚拟机将堆内存划分为新生代、老年代和永久代,永久代是HotSpot虚拟机特有的概念
在JDK 1.7中HotSpot已经开始了“去永久化”,把原本放在永久代的字符串常量池移出。永久代主要存放常量、类信息、静态变量等数据,与垃圾回收关系不大,新生代和老年代是垃圾回收的主要区域。
 
新生代(Young)
                                
       新生成的对象优先存放在新生代中,新生代对象朝生夕死,存活率很低,在新生代中,常规应用进行一次垃圾收集一般可以回收70% ~ 95% 的空间,回收效率很高。
       HotSpot将新生代划分为三块,一块较大的Eden空间和两块较小的Survivor空间,默认比例为8:1:1。划分的目的是因为HotSpot采用复制算法来回收新生代,设置这个比例是为了充分利用内存空间,减少浪费。新生成的对象在Eden区分配(大对象除外,大对象直接进入老年代),当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。
       GC开始时,对象只会存在于Eden区和From Survivor区,To Survivor区是空的(作为保留区域)。GC进行时,Eden区中所有存活的对象都会被复制到To Survivor区,而在From Survivor区中,仍存活的对象会根据它们的年龄值决定去向,年龄值达到年龄阀值(默认为15,新生代中的对象每熬过一轮垃圾回收,年龄值就加1,GC分代年龄存储在对象的header中)的对象会被移到老年代中,没有达到阀值的对象会被复制到To Survivor区。接着清空Eden区和From Survivor区,新生代中存活的对象都在To Survivor区。接着, From Survivor区和To Survivor区会交换它们的角色,也就是新的To Survivor区就是上次GC清空的From Survivor区,新的From Survivor区就是上次GC的To Survivor区,总之,不管怎样都会保证To Survivor区在一轮GC后是空的。GC时当To Survivor区没有足够的空间存放上一次新生代收集下来的存活对象时,需要依赖老年代进行分配担保,将这些对象存放在老年代中。
 
老年代(Old)
 
       在新生代中经历了多次(具体看虚拟机配置的阀值)GC后仍然存活下来的对象会进入老年代中。老年代中的对象生命周期较长,存活率比较高,在老年代中进行GC的频率相对而言较低,而且回收的速度也比较慢。
 
永久代(Permanent)(JDK 1.8之后将最初的永久代取消了,由元空间取代)
 
       永久代存储类信息、常量、静态变量、即时编译器编译后的代码等数据,对这一区域而言,Java虚拟机规范指出可以不进行垃圾收集,一般而言不会进行垃圾回收。
 
 
 
Minor GC 和 Full GC的区别
       新生代GC(Minor GC):Minor GC指发生在新生代的GC,因为新生代的Java对象大多都是朝生夕死,所以Minor GC非常频繁,一般回收速度也比较快。当Eden空间不足以为对象分配内存时,会触发Minor GC。
       老年代GC(Full GC/Major GC):Full GC指发生在老年代的GC,出现了Full GC一般会伴随着至少一次的Minor GC(老年代的对象大部分是Minor GC过程中从新生代进入老年代),比如:分配担保失败。Full GC的速度一般会比Minor GC慢10倍以上。当老年代内存不足或者显式调用System.gc()方法时,会触发Full GC。
 
 
 
1:eden、SurvivorFrom 复制到 SurvivorTo,年龄+1
首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到SurvivorFrom区,当Eden区再次触发GC的时候会扫描Eden区和From区域,对这两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域(如果有对象的年龄已经达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1
2:清空 eden、SurvivorFrom
然后,清空Eden和SurvivorFrom中的对象,也即复制之后有交换,谁空谁是to
3:SurvivorTo和 SurvivorFrom 互换
最后,SurvivorTo和SurvivorFrom互换,原SurvivorTo成为下一次GC时的SurvivorFrom区。部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代
 

JVM-4-堆内存划分的更多相关文章

  1. JDK8中JVM堆内存划分

    一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...

  2. 五、JVM之堆内存

    堆结构分代图 堆结构分代的意义 Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代.老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略. 堆内存是虚拟机管理 ...

  3. JVM中堆内存和栈内存的区别

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  4. jvm虚拟机--堆内存

    reserved 保留区域 堆 所有对象实例都在这里分配内存. 是垃圾收集的主要区域("GC 堆").现代的垃圾收集器基本都是采用分代收集算法,主要思想是针对不同的对象采取不同的垃 ...

  5. Java堆内存划分

    根据对象的存活率(年龄)Java堆内存划分为3种,新生代,老年代,永久代: 1.新生代 比如我们在方法中区new一个对象,那这方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象. 现在的商业虚 ...

  6. JVM的堆内存泄漏排查-性能测试

    JVM异常说明 https://testerhome.com/articles/24259 一文中已介绍了,JVM每个运行时区域--程序计数器 .Java虚拟机栈.本地方法栈.Java堆.方法区.直接 ...

  7. JVM之堆内存(年经代,老年代)

    一.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...

  8. G1垃圾收集器堆内存划分与角色分派【纯理论】

    接着上一次[https://www.cnblogs.com/webor2006/p/11123522.html]G1学习继续开启理论之旅.. G1的设计规划是要替换掉CMS[理想化的] G1在某些方面 ...

  9. 【转】JVM 堆内存设置原理

    堆内存设置 原理 JVM堆内存分为2块:Permanent Space 和 Heap Space. Permanent 即 持久代(Permanent Generation),主要存放的是Java类定 ...

  10. JVM探秘1--JVM内存运行时区域划分

    Java程序员一般不需要太关注内存,因为操作内存的权力都交给了Java虚拟机,但是Java程序员必须需要了解JVM是如何使用内存的,否则一旦内存出现泄漏或事溢出的话,就会一筹莫展不知道从哪去入手排查问 ...

随机推荐

  1. Prometheus学习系列(七)之Prometheus PromQL说明

    前言 本文来自Prometheus官网手册1.2.3 和 Prometheus简介1.2.3 PromQL操作符 一.二元操作符 Prometheus的查询语言支持基本的逻辑运算和算术运算.对于两个瞬 ...

  2. C++ STL容器

    不定长数组:vector vector是一个模板类,作用为创建一个不定长的数组 声明方式:vector<int>a或者vector<double>b这种类型的方式. 基本操作: ...

  3. OSG绘制空间凹多边形并计算其面积

    目录 1. 思路 1) 多边形分格化 2) 几何图元遍历 2. 实现 3. 参考 1. 思路 这个问题其实涉及到OSG中的两个问题:多边形分格化和几何图元遍历. 1) 多边形分格化 在OpenGL/O ...

  4. [转]UiPath Invoke Code

    本文转自:https://dotnetbasic.com/2019/08/uipath-invoke-code.html We will learn step by step tutorial for ...

  5. 属性文件——Java&Spring

    属性文件 什么是属性文件 ? 定义:一个扩展名为properties文件,属性文件都是以key-value(键值对)来保存文件的内容,如:log4j.properties,db.properties等 ...

  6. 默认值操作符(Freemarker的空值处理)

    默认值操作符: 使用形式例如: userName!default_expr 或 userName! 或 (userName)!default_expr 或 (userName)! 这个操作符允许你为可 ...

  7. chunked

    简介 chunked是一种HTTP协议的分块传输编码的机制,即一个HTTP消息可以分成多个部分进行传输,它对于HTTP请求和HTTP响应都适用.对于非持续连接,浏览器通过连接是否关闭来界定请求和响应实 ...

  8. [日常] linux设置环境变量

    比如首先在/etc/profile里面增加这几个环境变量 export PATH=$PATH:/mnt/f/ubuntu/goProject/go/binexport GOROOT=/mnt/f/ub ...

  9. Excel上下标如何设置?

    Excel表格怎么设置上下标?Excel上下标设置技巧 在21世纪的我们,平时的工作和学习中,经常会使用到一些专业的文档,比如方程式.数据的公式和科学计数等,其中均会涉及到许多的上下标符号输入以及使用 ...

  10. Vue+Vuex初体验

    首先: 安装vuex npm install vuex -S 需要有两个组件(HelloWord.vue 和 HelloDemo.vue)[组件自定义] 注册路由 注册store 测试 一.需要有两个 ...