ღゝ◡╹)ノ❤️

集中一点,登峰造极!

  menu
137 文章
0 浏览
1 当前访客
ღゝ◡╹)ノ❤️

jvm

聊聊垃圾回收器?

响应速度优先?

ParNew+CMS

cms回收垃圾分为四个阶段,初始标记,并发标记,重新标记,并发清除,其中只有初始标记和重新标记会造成STW。

吞吐量优先?

Parallel+Parallel Old

G1

区域化分代式,把堆内存分成很多小区域,垃圾回收的时候可以根据优先级,选择性的回收若干块,这样在既能满足低停顿时间,也能满足高吞吐量。

class是对象存在哪?

Class对象是存放在堆区的,不是方法区。

方法区存什么?

类的元数据(元数据并不是类的Class对象!Class对象是加载的最终产品,类的方法代码,变量名,方法名,访问权限,返回值等等都是在方法区的)才是存在方法区的。

三色标记算法

先看三色是什么:

  • 白色:没有检查(或者检查过了,确实没有引用指向它了)
  • 灰色:自身被检查了,成员没被检查完(可以认为访问到了,但是正在被检查,就是图的遍历里那些在队列中的节点)
  • 黑色:自身和成员都被检查完了

假设现在有白、灰、黑三个集合(表示当前对象的颜色),其遍历访问过程为:

1.初始时,所有对象都在 【白色集合】中;
2.将GC Roots 直接引用到的对象 挪到 【灰色集合】中;
3.从灰色集合中获取对象:
3.1. 将本对象 引用到的 其他对象 全部挪到 【灰色集合】中;
3.2. 将本对象 挪到 【黑色集合】里面。
4.重复步骤3,直至【灰色集合】为空时结束。
5.结束后,仍在【白色集合】的对象即为GC Roots 不可达,可以进行回收。

非垃圾变为了垃圾

标记过不是垃圾的,变成了垃圾,暂时浪费内存,肯定抗不过下一轮GC。

错杀

这个问题是比较致命的,如果错杀了,就会出现运行结果不符合预期的情况。这个是绝对不能发生的。这发生的情况只有一个,就是D是黑色的,E是灰色的,但是D又指向了G,和E断开了指向G。 因为D已经标记了是黑色,但是E断开了引用,所以G就当做了是白色的。这个时候如果不操作的话,就会把G错杀掉。这种问题是必须解决掉的。

出现这个问题的主要原因是,一个对象从被E引用,变更为了被D引用。那么对于D来说就是多了一个直接引用,对于E来说就是少了一个直接引用。我们可以从这两个方面入手来解决这个问题,对应了也有两个方案,分别是增量更新(Incremental Update) 和原始快照(SATB,Snapshot At The Beginning)。

增量更新
  增量更新是站在新增引用的对象(也就是例子中的A对象)的角度来解决问题。所谓增量更新,就是在赋值操作之前添加一个写屏障,在写屏障中记录新增的引用。比如,用户线程要执行:A.f = F;那么在写屏障中将新增的这个引用关系记录下来。标准的描述就是,当黑色对象新增一个白色对象的引用时,就通过写屏障将这个引用关系记录下来。然后在重新标记阶段,再以这些引用关系中的黑色对象为根,再扫描一次,以此保证不会漏标。

原始快照(SATB)
  原始快照是站在减少引用的对象(也就是例子中的B对象)的角度来解决问题。所谓原始快照,简单的讲,就是在赋值操作(这里是置空)执行之前添加一个写屏障,在写屏障中记录被置空的对象引用。比如,用户线程要执行:B.f=null;那么在写屏障中,首先会把B.f记录下来,然后再进行置空操作。记录下来的这个对象就可以称为原始快照。

对象包括什么

从上面的这张图里面可以看出,对象在内存中的结构主要包含以下几个部分:

  • Mark Word(标记字段):MarkWord用于存储对象自身的运行时数据, 如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。
  • Klass PointerClass对象指针):Class对象指针的大小也是4个字节,其指向的位置是对象对应的Class对象(其对应的元数据对象)的内存地址
  • 对象实际数据:这里面包括了对象的所有成员变量,其大小由各个成员变量的大小决定,比如:byteboolean是1个字节,shortchar是2个字节,intfloat是4个字节,longdouble是8个字节,reference是4个字节
  • 对齐:最后一部分是对齐填充的字节,按8个字节填充。

CMS和G1

相较于CMS,G1还不具备全方位、压倒性优势 。 比如在用户程序运行过程中,G1无论是为了垃圾收集产生的内存占用(Footprint) 还是程序运行时的额外执行负载(overload)都要比CMS要高。 从经验上来说,在小内存应用上CMS的表现大概率会优于G1,而G1在大内存应用上则发挥其优势

CMS:

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器

CMS收集器仅作用于老年代 的收集,是基于标记-清除算法的,它的运作过程分为4个步骤:

  • 初始标记(CMS initial mark)
  • 并发标记(CMS concurrent mark)
  • 重新标记(CMS remark)
  • 并发清除(CMS concurrent sweep)

优点 :并发收集、低停顿。

缺点

  • CMS收集器对CPU资源非常敏感。
  • CMS收集器无法处理浮动垃圾(Floating Garbage)。
  • CMS收集器是基于标记-清除算法,该算法的缺点都有。

G1

G1重新定义了堆空间,打破了原有的分代模型,将堆划分为一个个区域。与CMS的标记-清除算法不同,G1从整体来看是基于标记-整理算法 实现的收集器,从局部(两个Region之间)上来看是基于“复制 ”算法实现的。但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC

G1收集的运作过程大致如下:

  • 初始标记(Initial Marking) :仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这阶段需要停顿线程,但耗时很短
  • 并发标记(Concurrent Marking) :是从GC Roots开始堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长 ,但可与用户程序并发执行。
  • 最终标记(Final Marking) :是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行
  • 筛选回收(Live Data Counting and Evacuation) :首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。这个阶段也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。

调优

https://blog.csdn.net/guyue35/article/details/107950136

参数

https://zhuanlan.zhihu.com/p/127352212

JVM命令

  1. 1、jps
  2. 2、jinfo
  3. 3、jstat
  4. 4、jstack
  5. 5、jmap
  6. 6、jhat

标题:jvm
作者:哇哇哇哇
地址:https://wuxiangshi.vip/articles/2022/03/14/1647262042714.html