JVM 类加载机制 类加载过程 分配内存 垃圾收集 内存回收

JVM脑图下载,包含所有JVM知识点(https://download.csdn.net/download/zhangbo0733/86404524)
JVM笔记
类加载机制
类加载过程
java.exe调用底层的jvm.dll创建JAVA虚拟机(C++)
创建一个引导类加载器(C++)
C++调用java代码创建jvm启动器,sun.misc.launcher(单例)\n该类由引导类加载器负责加载创建其他类加载器
sun.misc.launcher.getLauncher.getclassloader.loadclass(“com.**.Test.java”)
加载完成后汇之星test。main()方法入口,运行结束后JVM销毁
双亲委派
引导类加载器:负责加载位于jre/lib下面的核心类库
扩展类加载器:负责加载位于jre/lib目录下ext扩展目录中的jar包
应用程序类加载器:负责加载classpath路径下的类包,就是自己写的类
其他类加载器:加载用户自定义路径下的类包
先找父类加载,父类找不到再自己加载
jvm整体结构和内存模型
jvm虚拟机
类加载子系统
运行时数据区
堆 -Xms -Xmx
年轻代 1/3 -Xmn
eden(8/10)
survivor
S0(1/10)
S1(110)
老年代2/3
栈 -Xss
局部变量表
操作数栈
动态链接
方法出口
本地方法栈
方法区(元空间) -XX:MetaspaceSize \n-XX:MaxMetaspaceSize
常量,静态变量,类信息
程序计数器
字节码执行引擎
概括各组思想
总结句避免使用缺乏思想的句子
总结句要说明行动产生的结果
找出结论间的共性
jvm对象创建与内存分配
对象的创建
类加载检查
虚拟机遇到new指令先去检查这个指令的参数能否在常量池中定位到一个类的符号引用,\n并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,先加载类
分配内存
划分内存的方法
指针碰撞(Bump The Pointer)默认方法
空闲列表(Free List)
解决并发问题
CAS(compare and swap)
本地线程分配缓冲(Thread Local Allocation Buffer TLAB)\n每个线程在堆中预先分配一小块内存
初始化
分配到的内存空间初始化为零值(不包括对象头)
设置对象头
Mark Word标记字段\n(32位占四字节,64位8字节)
哈希值
gc分代年龄
锁状态标志
线程持有锁
偏向线程ID
偏向时间戳
Klass Pointer类型指针(开启压缩4字节,关闭压缩8字节),类的元数据的指针
数组长度( 4 字节 只有数组对象才有)
执行init方法
按照程序员的意思进行初始化
对象大小与指针压缩
对象大小可以根据JOL-CORE包查看
jdk1.6开始 64位操作系统支持指针压缩 -XX:+UseCompressedOops()默认开启
找出结论间的共性
对象栈上分配
逃逸分析
标量替换:标量、聚合量
对象分配
Eden、
大对象直接进老年代
长期存活的对象进入老年代
对象动态年龄判断(survivor 区)
老年代空间分配担保
G1/ZGC/调优工具
G1收集器(-XX:+UseG1GC)
G1(Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器,复制算法
G1将Java堆划分为多个大小相等的独立区域(Region)JVM最多可以有2048个Region。\nRegion大小等于堆大小除以2048,-XX:G1HeapRegionSize"手动指定Region大小,
年轻代和老年代,都是region集合,可以不连续。年轻代默认5%“-XX:G1NewSizePercent”\n\n设置新生代初始占比,最多不超过60%可以通过“-XX:G1MaxNewSizePercent”调整。\nG1有专门分配大对象(超过了一个Region大小的50%,)的Region叫Humongous区,\n
初始标记STW-》并发标记-》最终标记STW-》筛选回收stw
筛选回收阶段首先对各个Region的回收价值和成本进行排序,\n\n根据用户所期望的GC停顿时间(可以用JVM参数\n-XX:MaxGCPauseMillis指定)来制定回收计划,
YoungGC /MixedGC/ Full GC
MixedGC
不是FullGC,老年代的堆占有率达到参数(-XX:InitiatingHeapOccupancyPercent)设定的值则触发,\n回收所有的Young和部分Old(根据期望的GC停顿时间确定old区垃圾收集的优先顺序)以及大对象区,\n正常情况G1的垃圾收集是先做MixedGC,主要使用复制算法,需要把各个region中存活的对象拷贝到\n别的region里去,拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次FullGC
什么场景适合使用G1
50%以上的堆被存活对象占用\n
对象分配和晋升的速度变化非常大
垃圾回收时间特别长,超过1秒
8GB以上的堆内存(建议值)
停顿时间是500ms以内
ZGC收集器(-XX:+UseZGC)
ZGC是一款JDK11中新加入的具有实验性质的低延迟垃圾收集器
支持TB量级的堆。最大GC停顿时间不超10ms。奠定未来GC特性的基础。最糟糕的情况下吞吐量会降低15%。
不分代(暂时)
小型Region 中型Region 大型Region
调优工具
Jmap
Jmap -histo id >log.txt
Jmap -heap pid
jmap‐dump:format=b,file=eureka.hprof 14660
Jstack
找出占用cpu最高的线程堆栈信息
使用命令top -p ,显示你的java进程的内存情况,pid是你的java进程号,比如19663
\n按H,获取每个线程的内存情况\n
找到内存和cpu占用最高的线程tid,比如19664
转为十六进制得到0x4cd0,此为线程id的十六进制表示
执行jstack19663|grep -A 104cd0,得到线程堆栈信息中4cd0这个线程所在行的后面10行,\n从堆栈中可以发现导致cpu飙高的调用方法
查看对应的堆栈信息找出可能存在问题的代码
Jinfo
Jinfo -flags pid
Jinfo -sysprops pid
Jstat
jstat -gc pid 最常用,可以评估程序内存使用及GC压力整体情况
jstat -gccapacity pid
jstat -gcnew pid
jstat -gcnewcapacity pid
jstat -gcold pid
jstat -gcutil pid
年轻代对象增长的速率\n可以执行命令 jstat -gc pid 1 000 1 0 (每隔1秒执行1次命令, 共执行10次)
那么可以执行命令 jstat -gc pid 300000 1 0 , 观察每次结果eden, survivor和老年代使用的变化情况,
垃圾收集
垃圾收集算法
分代收集理论
新生代:大量死亡-标记-复制
老年代-标记整理/清除\n(比复制算法慢十倍以上)
复制算法
标记整理算法
标记清除算法
1效率问题,标记对象多效率不高
2空间问题,产生大量不连续碎片
垃圾收集器
年轻代
serial收集器 -XX:+UseSerialGC\n\n-XX:+UseSerialOldGC
单线程-stop the word
简单高效,没有线程交互开销
parnew
-XX:+UseParNewGC 可以和CMS收集器配合使用。\n
新生代复制算法,老年代标记整理算法STW
parallel
-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代)
serail收集器的多线程版本,默认收集线程和CPU核数相同\n也可以用参数(-XX:ParallelGCThreads)指定
关注点是吞吐量(高效率的利用CPU)\n\n
新生代复制算法,老年代标记整理算法STW
JDK8默认使用
老年代
CMS
一种以获取最短回收停顿时间为目标的收集器。(提高用户体验)
标记清除算法 / -XX:+UseConcMarkSweepGC(old)
初始标记-》并发标记-》重新标记-》并发清理-》并发重置
初始标记:STW,记下GCROOTS能直接引用的对象,速度很快
并发标记:从GC ROOTS遍历。用户线程可能导致已标记对象变化状态
重新标记:修正并发标记用户线程导致标记变动的那部分对象的标记记录\n用到三色标记里面的增量更新算法做重新标记 STW\n\n
并发清理:开启用户线程,同时GC会对未标记的区域做清扫。此阶段新增\n对象会标记为黑色不做处理\n\n
并发重置:重置本次GC过程的标记数据
CPU资源敏感/无法处理浮动垃圾(并发标记和并发清理产生的垃圾无法处理)\n/标记-清理算法导致大量的空间碎片-\nXX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理\n/执行过程不确定性,收集器未执行完再次启动 consurrent model failure
SERAL OLD
serial的老年代版本,CMS收集器后背方案,\nJDK1.5之前和parallel搭配
parallel old
Parallel Scavenge收集器的老年代版本。
jvm参数
‐Xms3072M‐Xmx3072M‐Xmn2048M‐Xss1M‐XX:MetaspaceSize=256M\n‐XX:MaxMetaspaceSize=256M‐XX:SurvivorRatio=8\n很多优化无非就是让短期存活的对象尽量都留在survivor里,\n不要进入老年代,这样在minorgc的时候这些对象都会被回收,\n不会进到老年代从而导致fullgc。\n\n\n
垃圾收集底层算法
三色标记
黑色
对象已经被垃圾收集器访问过,所有引用也被扫描\n黑色代表扫描过,安全存活,黑色不可能直接指向白色对象
灰色
已经被垃圾收集器访问过,但至少还有一个应用未扫描
白色
未被访问过,开始到结束都是白色表示不可达要垃圾回收
多标-浮动垃圾
针对并发标记(还有并发清理)开始后产生的新对象,\n通常的做法是直接全部当成黑色,本轮不会进行清除。
在并发标记过程中,如果由于方法运行结束导致部分局部变量(gcroot)被销毁\n这个gcroot引用的对象之前又被扫描过(被标记为非垃圾对象),\n那么本轮GC不会回收这部分内存。
漏标-读写屏障
增量更新incremental update
增量更新就是当黑色对象插入新的指向白色对象的引用关系时,就将这个新插入的引用记录下来,\n等并发扫描结束之后,再将这些记录过的引用关系中的黑色对象为根,重新扫描一次。
原始快照\nsnapshot at the beginning \n SATB
就是当灰色对象要删除指向白色对象的引用关系时,就将这个要删除的引用记录下来,在并发扫描结束之后,\n再将这些记录过的引用关系中的灰色对象为根,重新扫描一次,这样就能扫描到白色的对象,将白色对象直\n接标记为黑色( 对象也有可能是浮动垃圾)
写屏障
写屏障实现SATB
写屏障实现增量更新
并发标记时对漏标的处理方案
CMS:写屏障+增量更新
G1,Shenandoah:写屏障+SATB
ZGC:读屏障
跨代引用
记忆集和卡表
在新生代可以引入记录集(RememberSet)
hotspot使用一种叫做“卡表”(cardtable)的方式实现记忆集,
内存回收
算法(判断对象死亡)
Gc Roots\n可达性算法分析
线程栈的本地变量
静态变量
本地方法栈的变量
引用计数法
常见引用类型
强引用
软引用
弱引用
虚引用
finalize()方法判断对象最终是否存活
第一次标记并进行筛选(没有覆盖finalize()方法直接回收)
第二次标记

你可能感兴趣的:(性能调优监控工具,JVM,jvm,java,开发语言)