12 JVM 垃圾回收(下)
Java 虚拟机的堆划分
Java 虚拟机将堆划分为新生代和老年代。其中新生代又被划分为 Eden 区,以及两个大小相同的 Survivor 区。
默认情况下,Java 虚拟机采取一种动态分配的策略,根据对象生成的速率,以及 Survivor 区的使用情况动态调整 Eden 区和 Survivor 区的比例。也可以通过参数 -XX:SurvivorRatio 来固定这个比例。需要注意的是,其中一个 Survivor 区会一直为空,因此比例越低浪费的空间越高。
当调用 new 指令时,它会在 Eden 区中划出一块作为存储对象的内存。由于堆内存是线程共享的,因此直接在这里划分空间是需要进行同步的。否则会出现两个对象公用一段内存的事故。
Java 虚拟机的解决方法是:每个线程可以向 Java 虚拟机申请一段连续的内存,比如 2048 字节,作为线程私有的 TLAB。这个操作需要加锁,线程需要维护两个重要的指针,一个指向 TLAB 中空余内存的起始位置,一个则指向 TLAB 末尾。
然后通过 new 指令,便可以直接通过指针加法来实现,即把指向空余内存位置的指针加上所请求的字节数。如果加法后空余内存指针的值扔小于或等于指向末尾的指针,则代表分配成功。否则,TLAB 以及没有足够的空间来满足本次新建操作。这个时候,便需要当前线程重新申请新的 TLAB。
当 Eden 区的空间耗尽了,这个时候 Java 虚拟机便会触发一次 Minor GC,来收集新生代的垃圾。存活下来的对象,则会被送到 Survivor 区。当发生 MinorGC时,Eden 区和 from 指向的 Survivor 区中的存活对象会被复制到 to 指向的 Survivor 区中,然后交换 from 和 to 指针,以保证下一次 Minor GC 时,to 指向的 Survivor 区还是空的。
Java 虚拟机会记录 Survivor 区中的对象一共被来回复制了几次。如果一个对象被复制 15 次,那么该对象将被晋升至老年代。如果单个 Survivor 区已经被占用了 50%,那么较高复制次数的对象也会被晋升至老年代。
Minor GC 有一个问题,那就是老年代的对象可能引用新生代的对象。在标记存活对象的时候,我们需要扫描老年代中的对象。如果该对象拥有对新生代对象的引用,那么这个引用也会被作为 GC Roots。这样的话,就相当于进行了一次全堆扫描。
卡表
针对上述的问题,HotSpot 给出了一种解决方案叫做卡表。该技术将整个堆划分为一个个大小为 512 字节的卡,并且维护一个卡表,用来存储每张卡的一个标示位。这个标示位代表对应的卡是否可能存在指向新生代对象的引用。如果可能存在,那么我们就认为这张卡是脏的。
在进行 Minor GC 的时候,我们不用扫描整个老年代,而是在卡表中寻找脏卡,并将脏卡中的对象加入到 Minor GC 的 GC Roots 里。当完成所有脏卡的扫描之后,Java 虚拟机便会将所有脏卡的标示位清零。
上述总结介绍了用卡表这种方式解决全堆扫描效率低下的问题,置于如何标记脏卡,如何更新脏卡就不做深入总结了。
问答
Q:请问JVM分代收集新生代对象进入老年代,年龄为什么是15而不是其他的?
HotSpot会在对象头中的标记字段里记录年龄,分配到的空间只有4位,最多只能记录到15
Q:GC ROOT到底指的是对象本身,还是引用?
严格来说应该是对象。像局部变量中存放的引用只是导致对象成为GC roots的原因。我个人倾向于将这些引用作为GC roots,因为GC是从这些地方出发开始探索的。看各人理解方便吧。
总结
本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。
关注本人公众号,第一时间获取最新文章发布,每日更新一篇技术文章。
12 JVM 垃圾回收(下)的更多相关文章
- JDK分析工具&JVM垃圾回收(转)
转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...
- JVM基础系列第8讲:JVM 垃圾回收机制
在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...
- Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法
在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...
- JVM垃圾回收?看这一篇就够了!
深入理解JVM垃圾回收机制 1.垃圾回收需要解决的问题及解决的办法总览 1.如何判定对象为垃圾对象 引用计数法 可达性分析法 2.如何回收 回收策略 标记-清除算法 复制算法 标记-整理算法 分带收集 ...
- JVM垃圾回收重要理论剖析【纯理论】
JVM学习到这里,终于到学习最兴奋的地方了---垃圾回收,在学习它之前还得对JVM垃圾回收相关理论知识进行了解,然后再通过实践来加深对理论的理解,下面直接开始了解相关的理论: JVM运行时内存数据区域 ...
- JVM内存管理和JVM垃圾回收机制
JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...
- 老李分享:jvm垃圾回收
老李分享:jvm垃圾回收 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478 ...
- jvm - 垃圾回收
jvm - 垃圾回收 注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注 垃圾回收的意义 它使得java程序员不再时时刻刻的关注内存管理方面的工作. 垃圾回 ...
- Java虚拟机学习笔记——JVM垃圾回收机制
Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...
随机推荐
- python 之开发工具 sublimetext 3
一.前言 由于个人工作内容太过于繁杂,记忆力又不好,为日后使用的方便,故简单的记录了本篇关于sublimetext 3的初始化安装和部分插件内容的记录.目前最新的版本也是3.0以上版本了,故我这里使用 ...
- ssh免密钥登录一例问题
今天遇到一个奇怪的问题,在同一机器上创建的普通用户使用 ssh-copy-id -i .ssh/id_rsa.pub root@192.168.3.254 建立与root用户的免密钥通信,结果死活还是 ...
- UOJ#126【NOI2013】快餐店
[NOI2013]快餐店 链接:http://uoj.ac/problem/126 YY了一个线段树+类旋转卡壳的算法.骗了55分.还比不上$O(n^2)$暴力T^T 题目实际上是要找一条链的两个端点 ...
- 使用pip 提示UnicodeDecodeError: 'ascii' codec can't decode解决方法
python目录 Python27\Lib\site-packages 建一个文件sitecustomize.py 内容写: import sys sys.setdefaultencoding('gb ...
- java调用摄像头
http://blog.csdn.net/xing_sky/article/details/43482213 原文地址:http://blog.csdn.net/zajin/article/detai ...
- 第十二篇、OC_仿淘宝商品详情页的翻页
// // GFBProductViewController.m // elmsc // // Created by MAC on 2016/11/26. // Copyright © 2016年 G ...
- Sass和gulp的简单了解
一.sass less css预处理器 sass里面有2种语法 第一种语法是sass 后缀名必须是sass 第二种语法是scss 后缀名必须是scss ...
- >详解< 广度优先搜索
>概念< 广度优先搜索 概念 (其实我也不是很明白)广度优先搜索(简称广搜)(别名宽度优先搜索).采用了树形结构.常用于寻找 最短路线问题. -The end- 2018.7.12
- session 关于localhost和本地IP地址 不共享问题
打比方, 一个请求 localhost:8080/test/test ,一个本地Ip(172.1.1.1:8080/test/test) 1.请求localhost方式 HttpSession s ...
- struts2、hibernate的知识点
以下内容是我在复习struts2.hibernate和spring的时候记下得到,部分书上找不到的内容来自网络 以下是网络部分的原文网站: http://blog.csdn.net/frankaqi/ ...