写点什么

简述 JVM 垃圾回收原理和秒杀系统难点

用户头像
林昱榕
关注
发布于: 2020 年 08 月 05 日

JVM 垃圾回收原理

从三个问题来看JVM垃圾收集原理:

1.垃圾收集发生在哪里?

在JVM内存布局中,包括程序计数器、java本地方法栈和java虚拟机栈、方法区、堆。其中,程序计数器、java本地方法栈和java虚拟机栈是线程私有区域,且随着线程创建而创建,销毁而销毁。同时这些内存在编译阶段便可确定,具有确定性。



所以,JVM垃圾回收的场所是堆和方法区,堆中的回收主要是对象的回收,方法区的回收主要是废弃常量和无用的类的回收。



2.如何识别垃圾对象?

有两种方式:引用计数法和可达性分析法。



引用计数法存在循环依赖的问题。因此,常用的是可达性分析法。可达性分析法简单理解是通过从GC Roots开始往下搜索,然后把能访问到的对象也不断加到GC Roots中,这个过程结束后,不在该集合中的对象即为垃圾对象。



GC Roots可以理解为堆外指向对内的引用,一般包括(但不限于)以下几种:

  • Java方法栈帧中的局部变量

  • 已加载类的静态变量

  • JNI handles

  • 已启动且未停止的Java线程



在可达性分析算法的实践中存在不少问题要解决,比如多线程环境下对对象引用的更新会导致GC Roots识别的误报(将引用设置为null)或漏报(将引用设置为未被访问过的对象)。



为解决该问题,传统垃圾回收算法采用“stop-the-world”,停止其他非垃圾回收线程,直到完成垃圾回收。其中,stop-the-world通过安全点机制来实现。



3.如何回收垃圾对象?

垃圾回收线程在JVM中自动执行,Java程序无法强制执行。其遵循两个特性:1、自动性(JVM线程自动启动);2、不可预期性(对象没有被引用了,何时被回收是不可预期的)。



垃圾回收算法

  • 清除:把死亡对象所占据的内存标记为空闲内存,并记录在空闲列表之中。问题是会造成内存碎片和分配效率低下(需要访问空闲列表,无法通过指针加法方式分配)。

  • 压缩:将存活对象聚集在内存区域的起始位置,问题是压缩算法的性能开销大。

  • 复制:将内存分为两等分,分别用from和to指针维护,并且只使用from指向的内存空间。问题是内存空的使用效率极低。



除了上面三种方式外,现代垃圾回收器会综合上述几种回收方式,结合它们优点的同时规避它们的缺点。比如,基于大部分的Java对象只存活一小段时间,而存活下来的小部分Java对象则会存活很长一段时间的假设,Java虚拟机采用了分代回收思想:新生代和老年代。



新生代用来存储新建的对象,当对象存活时间够长时,则将其移到老年代。



针对新生代的垃圾回收(Minor GC),采用标记-复制算法。Minor GC需解决老年代可能引用新生代对象的问题,HotSpot采用卡表技术来解决该问题,防止Minor GC对全堆扫描。



而老年代中因为对象存活率高、没有额外空间对它进行分配担保,必须使用“标记-清理”或“标记-整理”算法来回收。



秒杀系统的主要挑战及问题和核心架构思路

秒杀系统从整体上看就是在解决并发读并发写问题。如何做到高并发、高性能、高可用、数据一致性等都是其面临的挑战。



要考虑的问题主要包括:

  • 如何保证秒杀系统的公平性?

  • 如何实现秒杀时机的控制?

  • 如何设计请求过滤阀门机制?



核心的架构思路主要有:

  • 秒杀系统与正常业务系统独立开来;

  • 缩短请求路径(CDN、反向代理等);

  • 减少请求数(静态文件合并等);

  • 减少不必要的业务功能;

  • 资源静态化



发布于: 2020 年 08 月 05 日阅读数: 50
用户头像

林昱榕

关注

开心生活,努力工作。 2018.02.13 加入

还未添加个人简介

评论

发布
暂无评论
简述JVM 垃圾回收原理和秒杀系统难点