Review-JVM
总体介绍
JVM内存结构
JVM体系概述
Java8以后的JVM
GC作用域
常见的垃圾回收算法
引用计数
复制算法
标记清除
标记整理
JM垃圾回收的时候如何确定垃圾?什么是 GC Roots
什么是垃圾
简单的说就是内存中已经不再被使用到的空间就是垃圾
要进行垃圾回收,如何判断一个对象是否可以被回收
引用计数法
Java中,引用和对象是有关联的。如果要操作对象则必须用引用进行
因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,给对象中添加一个引用计数器,
每当有一个地方引用它,计数器值加1
每当有一个引用失效时,计数器值减1。
任何时刻计数器值为零的对象就是不可能再被使用的,那么这个对象就是可回收对象
那为什么主流的Java虚拟机里面都没有选用这种算法呢?其中最主要的原因是它很难解决对象之间相互循环引用的问题
枚举根节点做可达性分析(根搜索路径)
demo
java 可以做GCRoots的对象
- 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表
- 方法区中的类静态属性引用的对象。
- 方法区中常量引用的对象
- 本地方法栈中N( Native方法)引用的对象
JVM调优和参数配置,如何盘点查看MM系统默认值
JVM的参数类型
标配参数
X参数(了解)
-Xint 解释执行
-Xcomp 第一次使用就编译成本地代码
-Xmixed 混合模式
XX参数
Boolean类型
公式
-XX:+或者- 某个属性值
+表示开启 -表示关闭
是否打印GC收集细节
-XX:+PrintGCDetails
-XX:-PrintGCDetails
是否使用串行垃圾收集器
-XX:-UseSerialGC
-XX:+UseSerialGC
KV设值类型
公式
-XX:属性key=属性值value
-XX:MetaspaceSize=128m
-XX:MaxTenuringThreshold=15
jinfo举例,如何查看当前运行程序的配置
公式
jinfo -flag 配置项 进程编号
题外话(坑题)
两个经典参数:-Xms和-Xmx
-Xms <===>等价于 -XX:InitialHeapSize
-Xmx <====>等价于-XX:MaxHeapSize
查看JVM默认值
-XX:+PrintFlagsInitial
查看初始默认值
公式
java -XX:+PrintFlagsInitial -version
java -XX:+PrintFlagsInitial
常用的JVM基本配置参数有哪些
常用参数
-Xms
初始大小内存,默认为物理内存1/64
等价于-XX:InitialHeapSize
-Xmx
最大分配内存,默认为物理内存1/4
等价于-XX:MaxHeapSize
-Xss
设置单个线程的大小,一般默认为512K~1024K
等价于-XX:ThreadStackSize
-Xmn
设置年轻代大小
-XX:MetaspaceSize
设置元空间大小
元空间的本质和永久代类似,都是对JVM规范中方法区的实现,不过元空间与永久代之间最大的区别在于;元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,源空间的大小仅受本地内存限制。
-Xms10m -Xmx10m -XX:MetaspaceSize=1024m -XX:+PrintFlagsFinal
设置案例
-XX:+PrintGCDetails
输出详细GC收集日志信息
GC
FullGC
-XX:SurvivoRatio
-XX:NewRatio
-XX:MaxTenuringThreshold
设置垃圾最大年龄
强引用、软引用、弱引用、虚引用分别
整体架构
强引用(默认支持模式)
软引用
弱引用
软引用和弱应用的适用场景
虚引用
GCRoots和四大引用的小总结
对OOM的认识
Java.lang.StackOverflowError
递归调用 栈的大小默认为512K~1024K
Java.lang.OutOfMemoryError:Java heap space
Java.lang.OutOfMemeoryError:GC overhead limit exceeded
程序在垃圾回收上花费了98%的时间,却收集不回2%的空间,通常这样的异常伴随着CPU的冲高
Java.lang.OutOfMemeoryError:Direct buffer memory
Java.lang.OutOfMemeoryError:unable to create new native thread
Java.lang.OutOfMemeoryError:Metaspace
-XX:+PrintFlagsInitial命令查看本机的初始化参数,-XX:MetaspaceSize为21810376B(约20M)
GC垃圾回收算法和垃圾收集器的关系
GC算法(引用计数/复制/标清/标整)是内存回收的方法论,垃圾收集器就是算法落地实现
因为目前为止还没有完美的收集器出现,更加没有万能的收集器,只是针对具体应用最合适的收集器,进行分代收集
4种主要垃圾收集器
串行垃圾回收器(Serial)
它为单线程环境设计并且只使用一个线程进行垃圾回收,会暂停所有的用户线程。所以不适合服务器环境
并行垃圾回收器(Parallel)
多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景
并发垃圾回收器(CMS)
用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程
互联网公司多用它,适用于对响应时间有要求的场景
G1垃圾回收器
G1垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收
怎么查看服务器默认的垃圾收集器是那个?生产上如何配置垃圾收集器的?
怎么查看默认的垃圾收集器是哪个?
java -XX:+PrintCommandLineFlags -version
默认的垃圾收集器有哪些
垃圾收集器
部分参数预先说明
Server/Client模式分别是什么意思
新生代
串行GC(Serial)/(Serial Coping)
并行GC(ParNew)
并行回收GC(Parallel)/(Parallel Scavenge)
老年代
串行回收GC(Serial Old)/(Serial MSC)
并行GC(Parallel Old)/(Parallel MSC)
并发标记清除GC(CMS)
4个过程
-
初始标记(CMS initial mark)
-
并发标记(CMS concurrent mark)和用户线程一起
-
重新标记(CMS remark)
-
并发清除(CMS concurrent sweep)和用户线程一起
-
总体过程
优缺点
优点:
并发收集低停顿
缺点:
- 并发执行,对CPU资源压力大
- 采用的标记清除算法会导致大量碎片
垃圾收集器配置代码总结
底层代码
G1垃圾收集器
以前收集器特点
- 年轻代和老年代是各自独立且连续的内存块
- 年轻代收集使用单eden+S0 +S进行复制算法
- 老年代收集必须扫描整个老年代区域
- 都是以尽可能少而快速地执行GC为设计原则
G1是什么
底层原理
Region区域化垃圾收集器
最大好处是化整为零,避免全内存扫描,只需要按照区域来进行扫描即可
回收步骤
4步过程
常用配置参数(了解)
和CMS相比的优势
总结
生产环境服务器变慢,诊断思路和性能评估
整机:top
uptime,系统性能命令的精简版
CPU:vmstat
查看CPU(包含不限于)
查看额外
-
查看所有CPU核信息
mpstat -P ALL 2
-
每个进程使用cpu的用量分解信息
pidstat -u 1 -p 进程编号
内存:free
应用程序可用内存数
查看额外
pidstat -p 进程号 -r 采样间隔秒数
硬盘:df
查看磁盘剩余空闲数
磁盘IO:iostat
磁盘I/O性能评估
查看额外
pidstat -d 采样间隔秒数 -p 进程号
网络IO:ifstat
默认本地没有,下载ifstat
查看网络IO
假如生产环境出现CPU占用过高,如何分析思路和定位
结合Linux和JDK命令一块分析
案例步骤
- 先用top命令找出CPU占比最高的
- ps -ef或者jps进一步定位,得知是一个怎么样的一个后台程序
ps -ef|grep java|grep -v grep
- 定位到具体线程或者代码
ps -mp 进程 -o THREAD,tid,time
-m 显示所有线程
-p pid进程使用cpu的时间
-o 该参数后是用户自定义格式
4. 将需要的线程ID转换为16进制格式(英文小写格式)
windows系统计算器可以自动进行进制转化
printf "%x\n" 有问题的线程ID
- jstack 进程ID | grep tid(16进制线程ID小写英文) -A60
A60 前60行
对于JDK自带的JVM监控和性能分析工具用过哪些?一是怎么用的?
性能监控工具
- jps(虚拟机进程状况工具)
- jinfo(Java配置信息工具)
- jmap(内存映像工具)
- jstat(统计信息监控工具)