【转】Java中的新生代、老年代、永久代和各种GC
JVM中的堆,一般分为三大部分:新生代、老年代、永久代:
1 新生代
主要是用来存放新生的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。
新生代又分为 Eden区、ServivorFrom、ServivorTo三个区。
- Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
- ServivorTo:保留了一次MinorGC过程中的幸存者。
- ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者。
当JVM无法为新建对象分配内存空间的时候(Eden满了),Minor GC被触发。因此新生代空间占用率越高,Minor GC越频繁。
MinorGC的过程:采用复制算法。
- 首先,把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,一般是15,则赋值到老年代区)
- 同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区)
- 然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区。
2 老年代
老年代的对象比较稳定,所以MajorGC不会频繁执行。
在进行MajorGC前一般都先进行了一次MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。
MajorGC采用标记—清除算法:
- 首先扫描一次所有老年代,标记出存活的对象
- 然后回收没有标记的对象。
MajorGC的耗时比较长,因为要扫描再回收。MajorGC会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。
当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。
3 永久代
指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。
Class在被加载的时候被放入永久区域。它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。
在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。
- Major GC和Full GC区别
- Full GC:收集young gen、old gen、perm gen
- Major GC:有时又叫old gc,只收集old gen
Minor GC触发机制:
当年轻代满时就会触发Minor GC,这里的年轻代满指的是Eden代满,Survivor满不会引发GC。通过复制算法 ,回收垃圾。复制算法不会产生内存碎片。
复制算法————————
复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的。
当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址。
此时,空闲区间已经与活动区间交换,而垃圾对象现在已经全部留在了原来的活动区间,也就是现在的空闲区间。事实上,在活动区间转换为空间区间的同时,垃圾对象已经被一次性全部回收。
Major GC的触发机制:
Major GC又称为Full GC。当年老代空间不够用的时候,虚拟机会使用“标记—清除”或者“标记—整理”算法清理出连续的内存空间,分配对象使用。
Full GC触发机制:
(1)调用System.gc时,系统建议执行Full GC,但是不必然执行
(2)老年代空间不足
(3)方法区空间不足
(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存
(5)由Eden区、survivor space1(From Space)区向survivor space2(To Space)区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
当永久代满时也会引发Full GC,会导致Class、Method元信息的卸载。
虚拟机给每个对象定义了一个对象年龄(Age)计数器。如果对象在 Eden 出生并经过第一次 Minor GC 后仍然存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1。对象在 Survivor 区中每熬过一次 Minor GC,年龄就增加 1 岁, 当它的年龄增加到一定程度(默认为 15 岁)时,就会被晋升到老年代中。对象晋升老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold (阈值)来设置。
【转】Java中的新生代、老年代、永久代和各种GC的更多相关文章
- java的新生代 老年代 永久代
介绍得非常详细: 新生代回收:(复制算法) 在堆中,新生代主要存放的是哪些很快就会被GC回收掉的或者不是特别大的对象(是否设置了-XX:PretenureSizeThreshold 参数).复制算法的 ...
- JVM简介堆中新生代老年代浅析
一.JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成.1)程序计数器 几乎不占有内存.用于取下一条执行的指令.2)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx ...
- jvm中的年轻代 老年代 持久代 gc
虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...
- JVM 新生代老年代
1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- JVM新生代老年代详解
1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我 ...
- Java垃圾回收之老年代垃圾收集器
1.Serial Old 收集器(-XX: +UseSerialOldGC, 标记-整理算法) 1.1 单线程收集,进行垃圾收集时,必须暂停所有工作线程 1.2 简单高效,Client模式下默认的老年 ...
- 新生代老年代GC组合
新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中 在执行机制上JVM提供了串行GC(SerialGC).并行 ...
- 对象何时进入老年代、何时发生full gc
一.对象何时进入老年代 (1)当对象首次创建时, 会放在新生代的eden区, 若没有GC的介入,会一直在eden区, GC后,是可能进入survivor区或者年老代 (2)当对象年龄达到一定的大小 , ...
- GC 年轻代 老年代 持久代
转载自:http://www.cnblogs.com/yaoyuan23/p/5587548.html 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Gener ...
随机推荐
- SQL LAST() 函数
LAST() 函数 LAST() 函数返回指定的字段中最后一个记录的值. 提示:可使用 ORDER BY 语句对记录进行排序. SQL LAST() 语法 SELECT LAST(column_nam ...
- export,export default和import的区别以及用法
首先要知道export,import ,export default是什么 ES6模块主要有两个功能:export和import export用于对外输出本模块(一个文件可以理解为一个模块)变量的接口 ...
- golang web实战之二(iris)
之前写了一篇为:golang web实战之一(beego,mvc postgresql) 听说iris更好: 1. iris hello world package main import &quo ...
- python day05
数字类型 1.整型:整数 num = 1000000000000 type(num) --->int 2.浮点型:小数 num = 123.2341 type(num) --->float ...
- 前端架构师 摘自《前端架构设计》-micah godbolt
作为前端架构师,你经常需要制定,或至少能够掌握以上所列的每一项内容.流程中的任何一个环节出现问题,都会迅速演变为开发人员的痛苦,或者导致网站无法持续满足用户要求,甚至崩溃. 前端架构师的用户是开发人 ...
- Java异步NIO框架Netty实现高性能高并发
原文地址:http://blog.csdn.net/opengl_es/article/details/40979371?utm_source=tuicool&utm_medium=refer ...
- centos下使用nginx 配置websocket,https升级wss协议
服务端代码/***/ // 服务端代码 var express = require('express'); var app = express(); var path = require('path' ...
- varnish与squid缓存效率对比实例
前提:安装varnish.squid.webbench(压测工具) 注:varnish和squid机都未安装其他多余服务,服务器绑定域名为www.dannylinux.top (为同一台服务器,测试 ...
- Python——模块——fnmatch(文件名对比)
一.模块作用 fnmatch 模块主要用于文件名的比较,使用 Unix shell 使用的 glob 样式模式. 二.简单匹配 fnmatch() 将单个文件名与模式进行比较并返回布尔值,来看它们是否 ...
- ionic3创建选项卡
html页面 <ion-content padding> <ion-segment [(ngModel)]="tabs"> <ion-segment- ...