• 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
  • 相关阅读:
    c_str()函数
    Linux创建用户
    Linux vim替换命令
    计算器表达式求值源码
    结构体、共用体。面试必用
    Ubuntu打开中文输入法
    Unable to establish SSL connection
    变量的命名和使用
    C++ ARX二次开发-MFC 非模态对话框modaless dialog
    C++ ARX二次开发-创建三维实体
  • 原文地址:https://www.cnblogs.com/bananafish/p/13341904.html
Copyright © 2020-2023  润新知