写点什么

架构师训练营 第九周课程

用户头像
文江
关注
发布于: 2020 年 12 月 19 日

请简述 JVM 垃圾回收原理。


  1. JVM 垃圾回收是指将堆中不再使用的对象回收,该回收机制通过可达性算法识别垃圾回收对象,其具体的操作算法如下

  2. 从线程栈帧的局部变量,或者方法的静态变量出发,把这些变量引用的对象进行标识

  3. 看该对象是否引用了其它对象,如果有,则将其它对象也进行标记

  4. 以此类推,将所有变量遍历完毕

  5. 在堆中,没有被标记的对象就似乎可以被回收的对象

  6. JVM 垃圾回收过程,涉及到如下三个步骤

  7. 清理,标记不用的对象空间(并不会真的删除,知识标明该内存空间可用)

  8. 压缩,将存活的对象拷贝到一段连续的内存空间中,目的是尽可能保证可用空间是连续的,因为类似数组之类的存储结构,是需要连续的空间来存储

  9. 复制,对空间分为两部分 A 和 B,在 A 中新创建对象,当 A 中空间用完了,则将还生存的对象拷贝到空间 B 中,目的是将存活时间较长的对象移动到额外区域

  10. 垃圾回收思想

  11. 大部分时候 java 中对象的生存周期都是很短的,因此可以开辟一块较小的区域(新生区),用来存放新初始化的对象,因为空间较小,那么扫描的时间成本也会较低。如果经过一段时间,新生区的对象还没有回收,则可以移动到另外一块区域(老年代)

  12. 新生代区域分为三块,eden 区,from 区,以及 to 区。新创建的对象都是在 eden 区,当 eden 区满了,垃圾回收开始工作,将 eden 区垃圾回收,同时将还存活的对象迁移到 from 区或者 to 区。如果 from 区满了则迁移到 to 区,from 区清空。下次遍历就是便利 eden 区和 to 区,将不用对象迁移到 from 区。如果 from 区也满了,则将对象迁移到老年代。当老年代空间也满了,再对老年代区间垃圾回收

  13. 不同时期的 JVM 版本,对垃圾回收的实现也不同

  14. 早期是串行回收器,回收线程会阻塞当前用户执行的线程,称为 stop-the-world

  15. 下一步演化为并行的垃圾回收期,充分利用了 cpu 多核心。但垃圾回收时候,同样所有的回收线程也阻塞了用户线程,也是 stop-the-world

  16. 再进一步演化成并发回收器 CMS,该回收器分为四个部分

  17. 初始化标记,会 stop-the-world

  18. 并发标记,跟用户线程并行

  19. 重标记,多线程标记,stop-the-world,因为之前标记的时候,可能有用户线程新产生了,为了防止遗漏,需要阻塞所有用户线程,进行再次标记

  20. 并发清理(跟用户线程并行)

  21. 再一步演化为 G1 垃圾回收器

  22. G1 将内存分为更细的块(比如说切分成 2000 个小块,这些小块同样有 eden,from,to,老年区之类)

  23. 通过配置-xx:MaxGCPauseMillis,可以控制老年区的回收时间,进而控制 stop-the-world 时间


  • 设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?

  1. 主要挑战

  2. 大量的用户短时间并发请求,对服务器造成极大压力

  3. 当并发量是平时系统负载的几百倍时候,购买硬件扩充系统成本会非常高

  4. 架构思路

  5. 如果改造旧系统成本太高,不妨做一个新系统应对秒杀

  6. 如果短时间大并发的请求无法处理,根据秒杀的业务特性,只有少数用户能下单,不妨设计阀门机制,将用户请求直接拦截在下单系统外

  7. 尽可能将动态资源改为静态资源,使用 CDN 加速

  8. 减少对外部系统的访问频率,例如 DB

  9. 减少用户 http 请求次数

  10. 使用空白的 js 文件,这个空白 js 文件不缓存,放置到服务器中,因为是空文件,所以即使用户请求,也不会占用太多带宽,等到秒杀开始的时候,在该文件中填充商品 id 和随机生成的下单 url 地址,防止用户作弊。


发布于: 2020 年 12 月 19 日阅读数: 22
用户头像

文江

关注

还未添加个人签名 2020.04.02 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营 第九周课程