JVM体系大全
2020-04-22 10:26:17 0 举报
AI智能生成
马老师JVM的VIP课程总结,更新中
作者其他创作
大纲/内容
<b>1、虚拟机基础概念(来源:马士兵课程)</b><br><br>java -version :可以看到JVM的具体实现HotSpot,解释编译混合执行mixed mode(解释器 + 热点代码编译)<br> <b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-Xint</font></b> 使用解释模式,启动很快,执行稍慢<br> <b> <font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-Xcomp</font></b> 使用纯编译模式,执行很快,启动很慢<br> 检测热点代码: -XX:CompileThreshold = 10000<br><br>
<b>2、class文件结构<br><br>是什么:二进制字节流</b><br>
可以通过jdk自带的命令:<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;"><b>javap -v 目标class文件的绝对路径</b></font>,进行查看,或者通过IDEA插件:<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;"><b>jclasslib Bytecode viewer </b></font>
Magic Number
Minor Version
Major Version
constant_pool_count
constant_pool
1、CONSTANT_Utf8_info
tag:1 --占用空间一个字节
length:UTF-8字符串占用的字节数
bytes:长度为length的字符串
3、CONSTANT_Integer_info
tag:3
bytes:4个字节,Big-Endian(高位在前)存储的int值
4、CONSTANT_Float_info
tag:4
4个字节,Big-Endian的float值
5、CONSTANT_Long_info
tag:5
8个字节,Big-Endian的long值
6、CONSTANT_Double_info
tag:6
8个字节,Big-Endian的double值
7、CONSTANT_Class_info
tag:7
index:2字节,指向类的全限定名项的索引
8、CONSTANT_String_info
tag:8
2字节,指向字符串字面量的索引
9、CONSTANT_Fieldref_info
tag:9
index:2字节,指向声明字段的类或者接口描述符CONSTANT_Class_info的索引项
index:2字节,指向字段描述符CONSTANT_NameAndType的索引项
10、CONSTANT_Methodref_info
tag:10
index:2字节,指向声明方法的类或者接口描述符CONSTANT_Class_info的索引项
index:2字节,指向字段描述符CONSTANT_NameAndType的索引项
11、CONSTANT_InterfaceMethodref_info
tag:11
index:2字节,指向声明方法的类或者接口描述符CONSTANT_Class_info的索引项
index:2字节,指向字段描述符CONSTANT_NameAndType的索引项
12、CONSTANT_NameAndType_info
tag:12
index:2字节,指向该字段或方法名称常量项的索引
index:2字节,指向该字段或方法描述符常量项的索引
15、CONSTANT_MethodHandle_info
tag:15
refence_kind:1字节,1-9之间的一个值,决定了方法句柄的类型,方法句柄类型的值表示方法句柄的字节码行为
refence_index:2字节,对常量池的有效索引
16、CONSTANT_MethodType_info
tag:16
descriptor_index:2字节,指向Utf8_info结构表示的方法描述符
18、CONSTANT_invokeDynamic_info
tag:18
bootstrap_method_attr_index:2字节,当前Class文件中引导方法表的bootstrap_method[]数组的有效索引
name_and_type_index:2字节,指向NameAndType_info表示的方法名和方法描述符
access_flags
ACC_PUBLIC 0x0001 是否为public类型
ACC_FINAL 0x0010 是否为final
<span style="font-size: inherit;">ACC_SUPER 0x0020 该标志必须为真,JDK1.0.2之后编译出来的内容必须为真,指明invokespectial指令使用新语义</span><br>
ACC_INTERFACE 0x0200 是否接口
ACC_ABSTRACT 0x0400 接口或抽象类
ACC_SYNTHETIC 0x1000 编译器自动生成,非用户代码产生,http://www.jianshu.com/p/d571300810b3
ACC_ANNOTATION 0x2000
ACC_ENUM 0x4000
this_class
super_class
interfaces_count
interfaces
fields_count
fields
access_flags 2字节
ACC_PUBLIC -0x0001
ACC_PRIVATE - 0x0002
ACC_PROTECTED -0x0004
ACC_STATIC -0x0008
ACC_FINAL -0x0010
ACC_VOLATILE -0x0040
ACC_TRANSIENT -0x0080
ACC_FINAL -0x0010
ACC_ENUM -0x4000
name_index u2
descriptor_index u2
B - byte
C - char
D - double
F - float
I - int
J - long
S - short
Z - boolean
V - void
L - Object 例如:Lcom/botech/dispacher/Test
数组[
一维数组[B [Ljava/lang/Stirng
多维数组[[C [[[Ljava/lang/String
attributes_count
attributes
methods_count
methods
access_flags
ACC_PUBLIC -0x0001
ACC_PRIVATE - 0x0002
ACC_PROTECTED -0x0004
ACC_STATIC -0x0008
ACC_FINAL -0x0010
ACC_SUNCHORNIZED - 0x0020
ACC_BRIDGE - 0x0040 编译器产生的桥接方法 https://blog.csdn.net/mhmyqn/article/details/47342577
ACC_VARARGS -0x0080
ACC_NATIVE - 0x0100
ACC_ABSTRACT -0x0400
ACC_STRICTFP -0x0800 https://zhidao.baidu.com/question/451207689.html
ACC_SYNTHETIC -0x1000
name_index u2
descriptor_index u2
先参数列表(放在小括号内部),后返回值
void m() -> ()v
String toString() -> ()Ljava/lang/String;
long pos(int[] arr1,int arr2,long length) -> ([iiJ)J
attributes_count
attributes
attributes_count - u2
attributes
既有预定义属性,也可以自定义,java虚拟机自动忽略不认识的属性
Code - 方法表 - 该方法编译成的字节码指令
u2 attribute_name_index
u4 attribute_length
u2 max_stack
u2 max_locals
u4 code_length
code
u2 exception_table_length
exception_table
u2 attribute_count
attributes
ConstantVlue:字段表,final关键字定义的常量值
Deprecated:类、方法表、字段表
Exceptions:方法表
EnclosingMethod:类文件,局部类或匿名类的外部封装方法
InnerClasses:类文件,内部类列表
LineNumberTable:Code属性,java源码的行号与字节码指令的对应关系
LocalVariableTable:Code属性,方法局部变量表
SourceFile:类文件,源文件名
<b>自我总结:<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">class文件中除了上面这些固定位置信息后,其他的具体代码实际都对应着java虚拟机规范中的指令集,也就是java汇编码,例如:aload_0对应的十六进制是0x26,然后在class搜26就能找到具体方法中的对应。<br><br>这个感觉有点像将所有的信息都放入常量池中,然后根据不同的命令对常量池中的对象进行调用、操作等</font></b><br>
https://mp.weixin.qq.com/s/Zfv9SjQeAtjnT4xVwTsa2g
<b>java内存模型八大原子操作</b>
lock:锁定
作用于主内存,标识变量为线程独占
unlock:解锁
作用于主内存,解锁线程独占变量
read:读取
作用于主内存,读取内容到工作内存
load:载入
作用于工作内存,read后的值放入线程本地变量副本
use:使用
作用于工作内存,传值给执行引擎
assign:赋值
作用于工作内存,执行引擎结果赋值给线程本地变量
store:存储
作用于工作内存,存储到主内存给write备用
write:写入
作用于主内存,写变量值
<b>3、内存加载过程</b>
Loading(加载)
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;"><b>双亲委派机制,主要是考虑安全性,从上到下进行类加载<br>自顶而下:进行实际查找和加载 child方向<br>自下而上:检查该类是否已经加载 partent方向</b></font>
主要就是出于对安全的考虑
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">如何打破双亲委派机制?</font></b>
1、JDK1.2之前,自定义ClassLoader都必须重写loadClass()
2、ThreadContextClassLoader可以实现基础类调用实现类代码,通过thread.setContextClassLoader指定
3、热启动,热部署:osgi tomcat都有自己的模板指定classloader(可以加载同一类库的不同版本)
1、Bootstrap加载器
加载路径:sun.boot.class.path
2、Extension加载器
加载路径:java.ext.dirs
3、App加载器
加载路径:java.class.path
4、CustomClassLoader加载器
实现方式
继承ClassLoader
重写模板方法findClass
重写的findClass中,返回defineClass(四个参数)
使用场景
1、Spring中对class会进行动态代理(新的class)
2、tomcat加载自己的jar包
3、热部署,针对改动的文件手动load
Linking
Verification(校验)
校验class文件符不符合标准,例如:是不是以cafe babe开头的 <br>
Preparation(准备)
给静态成员变量赋默认值<br>
Resolution(解析)
将类、方法、属性等符号引用解析为直接引用<br>常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用
Initializing(初始化)
调用类初始化代码,给静态成员变量赋初始值
<b>4、运行时内存结构</b>
1、前置知识铺垫
计算机构成
2、数据一致性问题
1、缓存行cacheLine的存在,大多数为64字节
2、现代CPU的数据一致性 = 缓存锁(MESI缓存一致性协议) + 总线锁
3、位于同一缓存行的两个不同数据,被两个相同CPU锁定,产生互相影响的伪共享问题
3、乱序问题
1、问题现象:CPU中PC的指令会有多条,对于没有依赖关系的指令会发生乱系执行
2、合并写技术:WCBuffer,高于L1,容量非常小,4个字节(知识点比较偏),直接写到L2缓存
3、有序性保证
CPU级别内存屏障<br>IntelCPU
sfence:写操作前后串行
lfence:读操作前后串行
mfence:读写操作前后串行
汇编指令:lock
JVM级别内存屏障
LoadLoad:读操作前后串行
StoreStore:写操作前后串行
LoadStore:先读再写
StoreLoad:先写再读
JVM内存屏障不是仅依赖硬件级别的CPU屏障,也可以通过ock指令实现
具体实现:Volatile关键字
字节码层面:ACC_VOLATILE
JVM层面:通过内存屏障实现
OS及硬件层面:lock指令实现
synchronized实现细节
字节码层面:ACC_SYNCHRONIZED
JVM层面:monitorenter、monitorexit指令<br> C C++调用了操作系统提供的同步机制
OS及硬件层面:X86 : lock cmpxchg / xxx
4、对象相关问题
1、创建过程
1、class loading
2、class linking(verification preparation resolution)
3、class initializing
4、申请对象内存
5、成员变量赋默认值
6、调用构造方法<init>
1、成员变量顺序赋初始值
2、执行构造方法语句
2、内存布局
1、对象头:MarkWord 8个字节
对象头空间分布
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">引出一个问题:为什么GC年龄默认为15?,因为4个字节代表最大值就是15</font></b>
2、ClassPoint指针: -XX:UseCompressedClassPointers为4个字节,不开启为8个字节
<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">2.1、此为数组专用,存储数组长度,4字节</font>
3、实例数据(数组数据): 《-XX:UseCompressedOops为4字节,不开启为8个字节》针对引用类型<br> Ordinary Object Pointers
4、Padding对齐,8的倍数
5、运行时数据区(来源:图灵学院诸葛老师)
Heap(堆):<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">线程</font><font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">共享</font>
Stack(栈):<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">线程</font><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">独有</font>
局部变量表
操作数栈
比较典型的问题就是:<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;"><b>i=i++ 其实i不变</b></font>
动态链接
将符号引用解析为直接引用的过程
方法出口
Native Method Stacks(本地方法栈):<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">线程</font><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">独有</font>
Method Area(方法区):<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">线程</font><font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">共享</font>
具体实现A:Perm Space 永久区 (<1.8)
一旦确定无法改变大小,可能出现溢出现象
具体实现B:Meta Space 元空间(>=1.8)
受限于物理内存,比上面更大更灵活
包含常量池
存储Class的信息、方法编译完的信息、字节码、类静态变量等
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">其中字符串常量在1.7是在这的,1.8之后在【堆】里了</font>
Program Counter(程序技术器):<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">线程</font><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">独有</font>
<b>5、JVM常用指令</b>
命令行参考:<b><font color="#c41230">https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html</font></b>
指定垃圾回收器
<font style="--darkreader-inline-color:#f26d84;"><b style=""><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+UseSerialGC </font><font color="#181a1b" data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;">= Serial New (DefNew) + Serial Old</font></b></font>
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+UseParNewGC </font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">= ParNew + SerialOld</font></b>
<font style="--darkreader-inline-color:#f26d84;"><b style=""><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+UseConc(urrent)MarkSweepGC </font><font color="#181a1b" data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;">= ParNew + CMS + Serial Old</font></b></font>
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+UseParallelGC </font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">=</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b"> Parallel Scavenge + Parallel Old(1.8默认)</font></b>
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+UseG1GC</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b"> = G1</font></b>
设定日志参数
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause</font></b>
或者每天产生一个日志文件
<b>6、GC垃圾回收</b>
概览图(来源:图灵学院诸葛老师)
何为垃圾:没有任何引用指向,如何找到?
引用计数法
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">不可能解决的问题:循环引用</font></b>
根可达算法
根对象
线程栈变量
静态变量
常量池
JNI指针
GC的常用算法
Mark- Sweep(标记清除)
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">优势:</font>算法性对简单,存活对象比较多的情况下效率较高
<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">劣势:</font>两遍扫描,效率偏低。内存空间不连续容易产生碎片
Coping(拷贝)
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">优势:</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">适用于存活对象较少的情况,只扫描一次,效率提高没有碎片</font>
<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">劣势:</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">空间浪费,移动赋值对象,需要调整对象引用</font>
Mark - Compact(标记压缩)
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">优势:</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">不会产生碎片,方便对象分配,不会产生内存减半</font>
<font color="#00a650" data-darkreader-inline-color="" style="--darkreader-inline-color:#68ffb1;">劣势:</font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">扫描两次,需要移动对象,效率偏低</font>
分代年龄
年轻代(1/3)
MinorGC/YGC:年轻代空间耗尽触发
<font style="--darkreader-inline-color:#f26d84;"><font color="#af102b" data-darkreader-inline-color="" style="font-weight: bold; --darkreader-inline-color:#f26d84;">-Xmn </font><font color="#181a1b" data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;">新生代大小</font></font>
老年代(2/3)
MajorGC/FullGC:老年代空间耗尽触发
<font style="--darkreader-inline-color:#f26d84;"><b style="color: rgb(175, 16, 43); --darkreader-inline-color:#f26d84;" data-darkreader-inline-color="">-Xms:</b><font color="#181a1b" data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;">初始堆大小</font><b style="color: rgb(175, 16, 43); --darkreader-inline-color:#f26d84;" data-darkreader-inline-color=""> -Xmx:</b><span style="--darkreader-inline-color:#f26d84;"><font color="#181a1b" data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;">最大堆大小(放在这里有点不合适,知道就行吧)</font></span></font>
两者比例可以通过:<font style="--darkreader-inline-color:#61c9ff;"> <font style="--darkreader-inline-color:#f26d84;" color="#af102b" data-darkreader-inline-color=""><b style="">–XX:NewRatio</b></font></font><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;"> </font>来指定
对象何时进入老年代?
参数:<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">XX:MaxTenuringThreshold</font></b> 指定次数,默认15
垃圾回收15次的进入老年代
动态年龄:s1入s2超过5成,把年龄最大的放入老年代
分配担保:YGC期间,survivor区空间不够了,空间担保直接进入老年代
提升效率的分配细节
栈上分配(无需调整)
线程私有小对象
无逃逸
支持标量替换
线程本地分配TLAB(无需调整)
占用eden,默认1%
多线程的时候不用竞争eden就可以申请空间,提高效率
小对象
VM options:<font style="--darkreader-inline-color:#f26d84;"><b style="color: rgb(175, 16, 43); --darkreader-inline-color:#f26d84;" data-darkreader-inline-color=""><font style="--darkreader-inline-color:#fdcd5b;">-XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:-UseTLAB</font></b><font style="--darkreader-inline-color:#dfdcd7;" color="#181a1b" data-darkreader-inline-color=""><br> 去掉逃逸分析、去掉标量替换、去掉TLAB,效率会减半</font></font>
对象分配过程图
常见的垃圾回收器
概览图:<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">目前还不存在不stop-the-world的垃圾回收器,ZGC可以做到1-2ms以内</font>
年轻代
Serial
单线程串行回收、safe point、stop-the-world
Parallel Scavenge(默认)
多线程并行回收、stop-the-world
同下比较:吞吐量优先
ParNew
多线程并行回收、stop-the-world
同上比较:响应时间优先
老年代
Serial Old
标记压缩算法
Parallel Old(默认)
整理、压缩算法
CMS JDK1.4版本之后<br>(concurrent mark sweep)
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">开启了并发回收的先河</font>
回收阶段
初始标记(STW)
只标记root
并发标记
一个GC过程,8成的时间都是浪费在这里
在程序运行的同时,进行标记
重新标记(STW)
由于上面的运行的同时进行标记,达不到全部标记,所以要重新标记
并发清理
在清理的过程中还会产生新的垃圾:浮动垃圾
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">个人理解:这个有点类似于迭代开发</font></b>
CMS的弊端
内存碎片化
CMS不适用于大内存
碎片化会导致新生代对象无法进入老年代,会降级为Serial Old来进行标记压缩
浮动垃圾
同上,也会切换至Serial Old
<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:CMSInitiatingOccupancyFraction92% </font><font data-darkreader-inline-color="" style="--darkreader-inline-color:#dfdcd7;" color="#181a1b">阈值可以调低,留出浮动垃圾的空间</font></b>
垃圾回收器与内存大小的关系
Serial 几十M
PS 上百M—几个G
CMS 20G
G1 上百G
ZGC 4T-16T
7、调优相关
概念区分
内存泄漏 memory leak
内存溢出 out of memory
例子用到的命令
java -XX:+PrintCommandLineFlags HelloGC
java -Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags -XX:+PrintGC HelloGC<br> PrintGCDetails PrintGCTimeStamps PrintGCCauses
java -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags HelloGC
java -XX:+PrintFlagsInitial 默认参数值
java -XX:+PrintFlagsFinal 最终参数值
java -XX:+PrintFlagsFinal | grep xxx 找到对应的参数
java -XX:+PrintFlagsFinal -version |grep GC:查询GC相关的命令
GC日志详解
调优前的基础概念
吞吐量:用户代码时间 /(用户代码执行时间 + 垃圾回收时间)
响应时间:STW越短,响应时间越好
所谓调优,首先确定,追求啥?吞吐量优先,还是响应时间优先?还是在满足一定的响应时间的情况下,要求达到多大的吞吐量...
什么是调优?
1、根据需求进行JVM规划和预调优
2、优化JVM运行环境(慢、卡顿)
3、解决JVM运行过程中出现的各种问题(OOM)
系统CPU经常100%,如何调优?
分析:一定有线程在占用系统资源<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">(jps查看java进程、jinfo 进程ID)</font></b>
找出那个进程CPU高<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">(top)</font></b>
查看对象数量:<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">jmap -histo 进程ID | head -20、<br>jmap -dump:format=b,file=xxx pid(</font></b>线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">)</font></b><br>
在项目启动的时候加入参数:<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">-XX:+HeapDumpOnOutOfMemoryError</font></b>
很多服务器备份(高可用),停掉这台服务器对其他服务器不影响
在线定位:Arthas
该进程哪个线程CPU高<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">(top-Hp 进程ID)</font></b>
导出该线程的堆栈<b><font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">(jstack -l 线程ID转换成16进制、jstack 进程ID查看下面所有线程的状态)</font></b>
查找哪个方法(栈帧)消耗时间(jstack)
系统内存飙高,如何查找问题?
导出堆内存(jmap)
分析(jhat jvisualvm mat jprofiler)
如何监控:jstat jvisualvm jprofiler arthas top...
工具
jconsole
jvisualvm(JDK自带)
jprofiler(收费)
arthas
jvm(jinfo)
查看详细情况
thread(jstack)
查看有多少个线程
dashboard(top)
观察系统情况
heapdump(jmap -dump)
导出堆文件
<font color="#af102b" data-darkreader-inline-color="" style="--darkreader-inline-color:#f26d84;">jhat 文件名.hprof</font>(JDK自带)、MAT、jvisualvm
对堆文件进行分析
jad 类的路径(反编译)
动态代理生成类的问题定位
第三方的类(观察代码)
版本问题(确定自己最新提交的版本是不是被使用)
redefine(热替换)
目前有些限制条件:只能改方法实现(方法已经运行完成),不能改方法名, 不能改属性
0 条评论
下一页