jvm与GC 基本 二

来源:互联网 发布:php 读取json文件 编辑:程序博客网 时间:2024/04/29 05:13

jvm区域的基本结构

JVM区域总体分两类:heap区和非heap区。
heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)(eden和survivor 存在于新生区)、Tenured Gen(老年代-养老区)。
非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。

新生区

新生区里包含 Eden 和 survivor 。但是要理解新生区,必须先了解 GC 对新生区的操作和采用的算法。对新生区采用的算法是复制算法。

GC 会不断的扫描看这个对象是否有引用。如果没有这个对象就会被回收。
复制算法:是相对高效的回收方法,不适用于存活对象较多的场合 如老年代,主要是将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中(这样复制过来的好处是减少了内存碎片,如果直接在使用空间清除的话,那空间会很零散),之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
这个eden就相当于是使用空间,survivor就相当于是保留空间,通常情况下eden会比survivor大的多,因为eden和survivor都是属于新生代(还有老生代,jvm 将堆分为新生代和老生代),新生代里的对象一般都是朝生夕死,所以活下来的不多,所以保留空间小一些就好。
对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。

看下 Eden和survivor 内存使用的对比图

Eden space
这里写图片描述

Survivor space

这里写图片描述

可以看到 Eden 内存使用很不稳定,说明经常发生GC,而相比survivor 的内存使用 稳定些。

老年代

年老代(Tenured Gen):年老代主要存放JVM认为生命周期比较长的对象(经过几次的新生代的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁(譬如可能几个小时一次)。年老代主要采用标记-压缩的方式来避免内存碎片(将存活对象移动到内存片的一边,也就是内存整理)。

标记-压缩算法原理:它在标记-清除算法的基础上做了一些优化。标记-压缩算法首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。标记-压缩算法适合用于存活对象较多的场合,如老年代。

看下老年代的内存使用图
这里写图片描述

相比而言更加稳定些

持久区:

持久代(Perm Gen):持久代主要存放类定义、字节码和常量等很少会变更的信息。主要来源是类加载时产生的class对象,还有配置文件通过反射产生的 class对象

看下永久区的内存使用

这里写图片描述

0 0
原创粉丝点击