JVM内存:年轻代、老年代、永久代(推荐 转)
参考文章:
1.Java 新生代、老年代、持久代、元空间
2.Java内存与垃圾回收调优
3.方法区的Class信息,又称为永久代,是否属于Java堆?
Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象,如下图所示:
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old)。新生代 ( Young ) 又被划分为三个区域:Eden、S0、S1。 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
Java 中的堆也是 GC 收集垃圾的主要区域。GC 分为两种:Minor GC、Full GC ( 或称为 Major GC )。
1.年轻代
年轻代用来存放新近创建的对象,尺寸随堆大小的增大和减小而相应的变化,默认值是保持为堆大小的1/15,可以通过 -Xmn 参数设置年轻代为固定大小,也可以通过 -XX:NewRatio 来设置年轻代与年老代的大小比例,年青代的特点是对象更新速度快,在短时间内产生大量的“死亡对象”。
年轻代的特点是产生大量的死亡对象,并且要是产生连续可用的空间, 所以使用复制清除算法和并行收集器进行垃圾回收.对年轻代的垃圾回收称作初级回收 (minor gc)。
初级回收将年轻代分为三个区域, 一个新生代 , 2个大小相同的复活代, 应用程序只能使用一个新生代和一个复活代, 当发生初级垃圾回收的时候,gc挂起程序, 然后将新生代和复活代中的存活对象复制到另外一个非活动的复活代中,然后一次性清除新生代和复活代,将原来的非复活代标记成为活动复活代。将在指定次数回收后仍然存在的对象移动到老年代中,初级回收后,得到一个空的可用的新生代。
新生代几乎是所有 Java 对象出生的地方,即 Java 对象申请的内存以及存放都是在这个地方。Java 中的大部分对象通常不需长久存活,具有朝生夕灭的性质。 当一个对象被判定为 “死亡” 的时候,GC 就有责任来回收掉这部分对象的内存空间。新生代是 GC 收集垃圾的频繁区域。 当对象在 Eden 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳,则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域中,然后清理所使用过的 Eden 以及 Survivor 区域,并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。 但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。
2.老年代
Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法。
现实的生活中,老年代的人通常会比新生代的人 “早死”。堆内存中的老年代(Old)不同于这个,老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。因此,Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。 另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。
3.永久代
永久代是Hotspot虚拟机特有的概念,是方法区的一种实现,别的JVM都没有这个东西。在Java 8中,永久代被彻底移除,取而代之的是另一块与堆不相连的本地内存——元空间。
永久代或者“Perm Gen”包含了JVM需要的应用元数据,这些元数据描述了在应用里使用的类和方法。注意,永久代不是Java堆内存的一部分。永久代存放JVM运行时使用的类。永久代同样包含了Java SE库的类和方法。永久代的对象在full GC时进行垃圾收集。
Jvm区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
HotSpot虚拟机GC算法采用分代收集算法:
1、一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直到GC到来打破了他们平静的生活。GC会逐一问清楚每个对象的情况,有没有钱(此对象的引用)啊,因为GC想赚钱呀,有钱的才可以敲诈嘛。然后富人就会进入Survivor Space(幸存者区),穷人的就直接kill掉。
2、并不是进入Survivor Space(幸存者区)后就保证人身是安全的,但至少可以活段时间。GC会定期(可以自定义)会对这些人进行敲诈,亿万富翁每次都给钱,GC很满意,就让其进入了Genured Gen(养老区)。万元户经不住几次敲诈就没钱了,GC看没有啥价值啦,就直接kill掉了。
3、进入到养老区的人基本就可以保证人身安全啦,但是亿万富豪有的也会挥霍成穷光蛋,只要钱没了,GC还是kill掉。
分区的目的:新生区由于对象产生的比较多并且大都是朝生夕灭的,所以直接采用标记-清理算法。而养老区生命力很强,则采用复制算法,针对不同情况使用不同算法。
非heap区域中Perm Gen中放着类、方法的定义,jvm Stack区域放着方法参数、局域变量等的引用,方法执行顺序按照栈的先入后出方式。
GC工作机制
SUN的jvm内存池被划分为以下几个部分:
Eden Space (heap)
内存最初从这个线程池分配给大部分对象。
Survivor Space (heap)
用于保存在eden space内存池中经过垃圾回收后没有被回收的对象。
Tenured Generation (heap)
用于保持已经在survivor space内存池中存在了一段时间的对象。
Permanent Generation (non-heap)
保存虚拟机自己的静态(reflective)数据,例如类(class)和方法(method)对象。Java虚拟机共享这些类数据。这个区域被分割为只读的和只写的。
Code Cache (non-heap)
HotSpot Java虚拟机包括一个用于编译和保存本地代码(native code)的内存,叫做“代码缓存区”(code cache)。
简单来讲,jvm的内存回收过程是这样的:
对象在Eden Space创建,当Eden Space满了的时候,gc就把所有在Eden Space中的对象扫描一次,把所有有效的对象复制到第一个Survivor Space,同时把无效的对象所占用的空间释放。当Eden Space再次变满了的时候,就启动移动程序把Eden Space中有效的对象复制到第二个Survivor Space,同时,也将第一个Survivor Space中的有效对象复制到第二个Survivor Space。如果填充到第二个Survivor Space中的有效对象被第一个Survivor Space或Eden Space中的对象引用,那么这些对象就是长期存在的,此时这些对象将被复制到Permanent Generation。
若垃圾收集器依据这种小幅度的调整收集不能腾出足够的空间,就会运行Full GC,此时jvm gc停止所有在堆中运行的线程并执行清除动作。
参考文章:
1、JVM内存:年轻代,老年代,永久代
2、 JVM内存区域划分Eden Space、Survivor Space、Tenured Gen,Perm Gen解释 (很形象的解释)
JVM内存:年轻代、老年代、永久代(推荐 转)的更多相关文章
- 面试官,Java8 JVM内存结构变了,永久代到元空间
在文章<JVM之内存结构详解>中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化.作为面试官如果你还不知道,那么面试过程中是不是有些露怯? ...
- jvm中的年轻代 老年代 持久代 gc
虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...
- GC 年轻代 老年代 持久代
转载自:http://www.cnblogs.com/yaoyuan23/p/5587548.html 虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Gener ...
- java的新生代 老年代 永久代
介绍得非常详细: 新生代回收:(复制算法) 在堆中,新生代主要存放的是哪些很快就会被GC回收掉的或者不是特别大的对象(是否设置了-XX:PretenureSizeThreshold 参数).复制算法的 ...
- JAVA8 JVM内存结构变了,永久代到元空间
在文章<JVM之内存结构详解>中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化.作为面试官如果你还不知道,那么面试过程中是不是有些露怯? ...
- JVM的新生代、老年代、MinorGC、MajorGC
参考资料: http://blog.csdn.net/flamezyg/article/details/44673951 http://www.blogjava.net/ldwblog/archive ...
- JVM(二)JVM内存布局
这几天我再次阅读了<深入理解Java虚拟机>之第二章"Java内存区域与内存溢出异常",同时也参考了一些网上的资料,现在把自己的一些认识和体会记录一下. (本文为博主 ...
- JVM内存分配及GC流程
-verbose 这是查询GC问题最常用的命令之一,具体参数如: -verbose:class 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进行诊断. -verbose:gc 输 ...
- Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)
勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行 ...
- JVM入门——JVM内存结构
一.java代码编译执行过程 1.源码编译:通过Java源码编译器将Java代码编译成JVM字节码(.class文件) 2.类加载:通过ClassLoader及其子类来完成JVM的类加载 3.类执行: ...
随机推荐
- Sequential Container
Notes from C++ Primer Initialize container by iterator When copy a container to another, the contain ...
- JVM自动内存管理机制——Java内存区域(下)
一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...
- git checkout tags with the same name as a branch
显式指定某个 tag git checkout refs/tags/ git checkout refs/tags/v0.1 显式指定某个 branch git checkout refs/heads ...
- Devops流程规范
芯盾时代_Devops_Docker操作说明及使用规范 北京芯盾时代科技有限公司 2019年1月 修订记录 版本号 修订人 修订日期 修订描述 v0.1 芯盾 2019/1/15 初次创建 v0.2 ...
- 带你入门 Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...
- 【BJOI2019】排兵布阵 DP
题目大意:有$n$座城堡,$s$轮游戏. 对于第$x$轮,第i座城堡的士兵数量为$a[x][i]$. 如果你需要攻下第i座城堡,你在第i座城堡部署的士兵必须严格大于$2a[x][i]$,如果攻下了你会 ...
- linux中一些简便的命令之tac/comm
tac tac是cat的反写,即反序显示文件内容 如文件a.txt内容如下: 1 2 3 4 5 则tac a.txt打印如下: 54321 我们可以使用awk来实现tac的功能: awk '{arr ...
- 一些oracle的经验
注:再写存储过程的时候,在for循环里要写begin和end,这样就可以写exception ,让这条错误数据回滚,然后记录错误日志,commit 关键字: oracle 存储过程 1.基本结构 CR ...
- ADSL 动态IP拨号VPS 软件配置
http://yun.baidu.com/share/link?uk=2520566727&shareid=330788421&third=0&adapt=pc&fr= ...
- 利用python数据分析与挖掘相关资料总结
小生今年研二,目前主要从事软件工程数据挖掘与分析.之前一直苦于找不到一个从数据预处理.数据分析.数据可视化和软件建模的统一平台.因此,小生辗转反辙学习了java,R语言,python,scala等等. ...