方法区的垃圾回收
方法区存放着一些常量(字符串,整型…),类的信息(Class),
且在1.7中位于永久代(Permanent General),发生垃圾收集的可能比较小,
但并非不会进行垃圾收集,
方法区的收集主要分为两部分
1.废弃的常量
当没有引用再指向一个常量时,也就是程序无法再获取到该常量时,(和对象的死亡差不多)
当进行垃圾收集时,垃圾收集器觉得有必要的话,会对该废弃常量进行收集
2.不使用的类型Class类
回收Class类型的条件比较苛刻,必须满足以下条件
该类的所有实例都以回收,也就是堆中没用该类的对象 |
---|
加载该类的类加载器已经回收,(很难达成) |
该类所对应的Class类对象没用被任何引用,不能被反射使用 |
显示类的加载和卸载信息的JVM参数(只能在product版本的虚拟机中使用)
-verbose: class |
---|
-XX: +TraceClass-Loading |
-XX: +TraceClassUnloading |
本来想换以下jdk版本试一试上诉的参数,下了新版jdk又觉得挺麻烦,还是不搞事了
分代收集理论
大多数的虚拟机的垃圾收集器的工作都基于分代收集理论
垃圾收集器的一致性收集原则,即将Java堆划分出一定的区域,按区域对对象进行存储和收集
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6gyLTUWZ-1631979190654)(F:\LocalTyproPictrue\s1231231.png)]
Young GC/Minor GC 指目标只是新生代的收集 |
---|
Major GC/Old GC 指目标只是老年代的收集,(只有CMS收集器会有只收集老年代的行为,在一些资料上与整堆Full GC混淆,) |
Mixed GC 指目标是整个新生代和部分老年代的收集(目前只有G1 收集器支持) |
Full GC 指对整个Java堆和方法区的收集 |
使用-XX:+PrintGCDetails把jdk17的垃圾日志打开看一看
再对比以下正在使用的jdk8的垃圾收集日志
这里明确的将新生代划分为了
**eden,from,to三个区,**但日志并没有告诉使用的是什么垃圾收集器
那去cmd里查一下
放到网上查了一下
ParallelGC代表
但垃圾收集日志的老年代显示的为ParOld,明显使用了ParallelOld堆老年代进行收集,
这是因为在开启UserParallelGC的环境下,也会默认开启UserParallelOldGC,所以使用了ParOld
这里有一个具体说明的连接
JVM默认老年代回收是 PSMarkSweep(Serial-Old) 还是Parallel Old? - 知乎 (zhihu.com)
所以不同的垃圾收集器设计上还是有很大区别的
垃圾收集算法
1.标记----------------清除算法
最基础的垃圾回收算法
算法分为标记和清除两个过程
概念:标记出所有需要回收的对象,完成后统一回收所有标记的对象
二个缺点
1.大量的标记和清除动作,执行效率不稳定
2.空间碎片化,导致出现内存碎片,不利于之后大对象的创建
2.标记----------------复制算法
也是现在大多数垃圾收集器使用的算法
上述的jdk8的垃圾收集日志也可以验证
概念:将内存划分为两块,每次只使用其中一块,但使用的那一块内存用完了,
就将其中还在使用的对象(活着的对象)复制到没使用的内存,
再将使用过的那块内存清空
优点:不会产生内存碎片。
简单,操作效率高
缺点:浪费了一半的内存空间
(Appel式回收:将新生代分为一个Eden区,和两个较小的survivor区,每次使用Eden区和一个survivor区,当发生垃圾回收时,将Eden区和使用的survivor区的存活对象复制到林一个survivor区,然后清除调Eden区和使用过的survivor区)
Hotspot虚拟机将Eden区和survivor区的比例设置为8:1,因为有两个survivor区,所有每次可使用的新生代空间总是为90%,
当survivor区在一次MinorGC时无法容纳全部的存活对象时,需要借助其他的内存空间,(进入老年代内存?)
3.标记----------------整理算法
针对上诉标记,复制算法不适合在老年代进行收集(如果对象的存活率较高,则需要频繁的进行对象的复制,而对于存活率较高的老年对象不适合频繁的复制和移动)
概念:在标记了所有的存活对象后,将所有对象都向内存的一边移动,然后在将边界外的内存全部清空(与标记----清除算法的区别是,前者是非移动式的,后者是移动式的)
对象移动操作的利弊
对象的移动操作需要全程暂停用户程序,(不然肯定会有内存错误了),
这种暂停被称为 ‘Stop the world’ (幻视 The world扎瓦鲁多)
但如果不移动虽然能够减少这种暂停所需要的时间,但也会造成内存的碎片(影响程序的吞吐量)
PS(Parelle Scanvenge关注吞吐量的,采用标记整理,CMS则是标记—清除)