陕西 网站建设首选公司,在线设计免费签名,学科专业建设规划,网易 自助网站建设#x1f916; 作者简介#xff1a;努力的clz #xff0c;一个努力编程的菜鸟 #x1f423;#x1f424;#x1f425; #x1f440; 文章专栏#xff1a;《JVM 学习笔记》 #xff0c;本专栏会专门记录博主在学习 JVM 中学习的知识点#xff0c;以及遇到的问题。 … 作者简介努力的clz 一个努力编程的菜鸟 文章专栏《JVM 学习笔记》 本专栏会专门记录博主在学习 JVM 中学习的知识点以及遇到的问题。 文章详情 本篇博客是学习 【狂神说Java】JVM快速入门篇 的学习笔记关于 GC垃圾回收机制 (堆内存结构、GC分类、四大垃圾回收算法) 知识点的学习总结由于这三个知识点的相互联系所以放在一起进行描述介绍。 ʜᴀ͟ᴘ͟ᴘ͟ʏᴇᴠᴇʀʏᴅᴀʏ̆̈ 一、堆
1. JVM体系结构图 简单回顾下 JVM体系结构图 后续将针对 堆 进行展开学习。 2. 堆
Heap 堆一个JVM实例只存在一个堆内存堆内存的大小是可以调节的
类加载器读取了类文件后需要 把类方法常变量放到堆内存中保存所有引用类型的真实信息以方便执行器执行 堆内存逻辑上分为三部分新生养老永久 (元空间 : JDK8 以后名称) GC垃圾回收主要是在 新生区和养老区又分为 轻GC 和 重GC。
如果内存满了OOM 堆内存不够就会导致java.lang.OutOfMemoryError: Java heap space
堆内存结构新生区 Young Generation SpaceYoung/New养老区 Tenure generation spaceOld/Tenure永久区 Permanent SpacePerm新生区
新生区是类诞生成长消亡的区域一个类在这里产生应用最后被垃圾回收器收集结束生命。
新生区又分为两部分伊甸区Eden Space和幸存者区Survivor Space所有的类都是在伊甸区被new出来的
幸存区有两个0区 和 1区
当伊甸园的空间用完时程序又需要创建对象JVM的垃圾回收器将对伊甸园区进行垃圾回收 (Minor GC)。 养老区
将伊甸园中的剩余对象移动到幸存0区若幸存0区也满了再对该区进行垃圾回收然后移动到1区那如果1区也满了呢
这里幸存0区和1区是一个互相交替的过程
就再移动到养老区若养老区也满了那么这个时候将产生 MajorGCFull GC进行养老区的内存清理若养老区执行了Full GC 后发现依然无法进行对象的保存就会 产生OOM异常“OutOfMemoryError ”。
如果出现 java.lang.OutOfMemoryErrorjava heap space异常说明Java虚拟机的堆内存不够原因如下
1、Java虚拟机的堆内存设置不够可以通过参数 -Xms初始值大小-Xmx最大大小来调整。
2、代码中创建了 大量大对象并且长时间不能被垃圾收集器收集存在被引用或者死循环了。 永久区Perm
永久存储区是一个常驻内存区域用于存放JDK自身所携带的ClassInterface的元数据也就是说它存储的是运行环境必须的类
信息被装载进此区域的数据是不会被垃圾回收器回收掉的关闭JVM才会释放此区域所占用的内存。
如果出现 java.lang.OutOfMemoryErrorPermGen space 说明是 Java虚拟机对永久代Perm内存设置不够。一般出现这种情况
都是程序启动需要加载大量的第三方jar包。
例如在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载最终导致Perm区被占满。
Jdk1.6之前 有永久代常量池1.6在方法区
Jdk1.7 有永久代但是已经逐步 “去永久代”常量池1.7在堆
Jdk1.8及之后无永久代常量池1.8在元空间 二、GC分类 熟悉堆的三区结构后方可学习JVM垃圾回收机制。 记住GC口诀 分代收集算法
次数频繁Young区次数较少Old区基本不动Perm永久区区 JVM在GC时并非每次都对上面三个内存区域一起回收的大部分时候回收的都是新生代
GC安装回收的区域分成两种普通GCminor GC全局GCmajor GC or Full GC
普通GC只针对新生代的GC
全局GC针对老年代的GC偶尔伴随对新生代的GC以及对永久代的GC 三、GC四大算法
1. 引用计数法
每个对象有一个引用计数器当对象被引用一次则计数器加1当对象引用失效一次则计数器减1 对于计数器为0的对象意味着是垃圾对象可以被GC回收。
目前虚拟机基本都是采用 可达性算法 从 GC Roots 作为起点开始搜索那么整个连通图中的对象里边都是活对象对于GC Roots 无法到达的对象变成了垃圾回收对象随时可被GC回收。 2. 复制算法 年轻代中使用的是 Minor GC采用的就是 复制算法 (Copying) 好处没有内存碎片坏处浪费内存空间
劣势 1、他浪费了一半的内存这太要命了.
2、如果对象的存活率很高我们可以极端一点假设是100%存活那么我们需要将所有对象都复制一遍并将所有引用地址重置一遍。
复制这一工作所花费的时间在对象存活率达到一定程度时将会变的不可忽视所以从以上描述不难看出。 复制算法要想使用最起码对象的存活率要非常低才行而且最重要的是我们必须要克服50%的内存浪费。 3. 标记清除Mark-Sweep 扫描Mark从根集合开始扫描对存活的对象进行标记 清除Sweep扫描整个内存空间回收未标记的对象使用free-list记录可用区域 优点不需要额外的空间
缺点两次扫描验证浪费时间会产生内存碎片 4. 标记清除压缩算法Mark-Sweep-Compact
进一步优化——标记压缩Mark-Compact 最终版本算法 —— 先标记清除几次再进行压缩 总结 内存效率复制算法 标记清除算法 标记整理算法 (时间复杂度) 内存整齐度复制算法 标记整理算法 标记清除算法 内存利用率标记整理算法 标记清除算法 复制算法 可以看出效率上来说复制算法是当之无愧的老大但是却浪费了太多内存而为了尽量兼顾上面所提到的三个指标标记整理算法相对来说更平滑一些 但是效率上依然不尽如人意它比复制算法多了一个标记的阶段又比标记清除多了一个整理内存的过程。 【问】难道就没有一种最优算法吗
答案 无没有最好的算法只有最合适的算法 —— GC: 分代收集算法 年轻代 存活率低使用复制算法 老年代 区域大存活率高标记清除内存碎片不是太多的时候 标记压缩混合 点击可快速回到文章开头文章顶部