Fork me on GitHub

Java学习----JVM学习

JVM 学习

如何判断一个对象是否是垃圾

  • 引用计数法

    如果有一个对象指向这个对象计数+1

    取消一个引用对象技术-1

    若减为0则回收

    无法解决循环引用

  • 根可达算法(JVM使用的方法)

    main函数启动的时候会产生一个GC Root 每个对象若可达root则不是垃圾,否则将被是为垃圾

    Root包括:

    1. JVM stack
    2. native method stack
    3. runtime constant pool
    4. static references in method area
    5. Clazz

JVM 垃圾回收算法

  • Mark-Sweep(标记清除)

    将垃圾标记后清除(会有许多碎片化的内存区域)

  • copying(拷贝)

    有两个内存区域,将一个区域有用的对象拷贝到另个区域(消耗内存)

  • Mark-Compact(标记压缩)

    将碎片整理好(消耗CPU)

JVM 垃圾回收器

分代:

分代模型分为新生代,老年代

绝大多数对象在新生代回收掉

新生代(Copy垃圾回收算法):

  • 8: eden

  • 1:survivor *2

    这两个区域会不停的复制,每复制一次都会进行将对象的年龄放入老年代

    若这两个区域满了会将对象直接放入老年代

老年代(Mark Compact):

  • tenured

PS: 对象在创建的时候若对象不大则在栈中创建,若太大则直接放入垃圾回收器。

若对象放入不了YGC放入老年代,若能在YGC放入则放入YGC。

在YGC中,没被回收对象经过路线,eden->survivor1 ->eden->survivo1 ->survivor 2->survivo1

之后就在surivivor1和survivo2中往返若年龄符合老年代标准放入老年代。

在这之中被回收对象在GC中的生命周期结束

打印所有可调参数: java -XX:+PringCommandLineFlags

分代回收器:

  • Young: Serial ParNew Parallel Scavencge
  • Old: CMS Serial Old Parallel Old

不分代回收器:

  • G1 ZGC

垃圾回收

Serial: 每过一段时间所有线程停止STW(stop the world) 单个线程垃圾回收线程进行垃圾回收

Parallel Scavencge:根serial一样,只不过使用多个线程进行垃圾回收

ParNew:它根Parallel Scavencge差不多,它只是配合CMS一起使用的

并发标记

在CMS并发标记的时候,当一个被标记了,工作线程中又出现了对象引用它,这种称为错标。

CMS的解决方法是重新标记,这里采用的算法为三色标记法(黑,白,灰)

并发标记法(三色标记法)

白色:未被标记的对象

灰色:自身被标记,成员变量没被标记

黑色:自生被标记,成员变量均被标记

错标产生情况:

假如 A 指向 B , B 指向 C [A->B->C]

A(黑色) 自己已经被标记,成员变量也标记完了。

B(灰色) 自己被标记完了,C没被标记

C(白色) 没有被标记

这时候 B->C 消失变为 A->C

这时候垃圾回收器会将C 给回收。

错标解决办法:

将A 重新标记为灰色,垃圾回收器重新进行标记,这时是又STW的

漏标产生情况:

A 的 第一个属性被标记了,第二个属性正在标记中第一个属性引用了C

当第二个属性标完后,整体为黑色,但是C对象仍然是白色的,最终C漏标了

CMS 在内存大的时候,remark 标记阶段的时间仍然很长。

G1

G1采取逻辑分代物理不分代

G1同样使用三色标记法,

与CMS不同的是G1采取的是:SATB (Snapshot At the Begining)[写屏障]

G1与CMS的不同做法是在标记的时候,将对象放入一个队列中去。

之后remark只扫描队列中的对象

JVM 线上问题解决

jps

列出Java进程

jinfo

jvm 基本信息

jstak 进程号

jvm进程上运行的线程状态

这个命令可以用来定位死锁

jstat -gc 进程号

统计gc的信息

jmap -histo 进程号

定位哪些对象在吃内存 注意,这个命令会引起系统卡顿(线上不能用)

jmap -dump:format=b,file=xxx.hprof 进程号 将堆存成一个文件

之后我们可以使用一些工具来分析这些堆内存,例如:

  • mat
  • jprofiler
  • jhat
  • jvisualvm

jvm自带图形化工具

jdk安装目录的bin目录

  • jvisualvm
  • jconsole

arthas

阿里开源的工具

arthas

  • dashboard 用字符界面模拟的图形界面
  • jvm 把jvm的所有信息输出
  • thread 把所有线程所列出来
  • thread -b 查看死锁
  • heapdump 相当于jmap
  • jad 类名 将java源码反编译
  • redefine class路径 将文件热更新到线上去

排查

  • jvm突然升高

    1. 使用arthas查看CPU占用最高的线程
    2. 若是业务线程则表示有大量计算操作
    3. 若是JVM线程则表示有频繁的FGC
posted @ 2020-07-19 23:01  Banana_Fish  阅读(267)  评论(0编辑  收藏  举报