对象的创建过程1. class loading2. class linking (verification, preparation, resolution)Verfication验证文件是否符合JVM规定Preparation静态成员变量赋默认值Resolution将类、方法、属性等符号引用解析为直接引用3. class initializing调用类初始化代码给静态成员变量赋初始值4. 申请对象内存5. 成员变量赋默认值6. 调用构造方法init成员变量顺序赋初始值执行构造方法语句普通对象1. 对象头markword 82. ClassPointer: -XX: UseCompressedClassPointers为4字节不开启为8字节3. 实例数据 引用类型 -XX: UseCompressedOops为4字节不开启为8字节4. padding对齐8的倍数数组对象1. 对象头markword 82. ClassPointer指针同上3. 数组长度4字节4. 数组数据5. padding对齐 8的倍数markword 64位1. hashCode部分31位hashcode - System.identityHashCode按原始内容计算的hashcode重写过的hashcode方法计算的结果不会存在这里。无用的类1. 该类所有的实例都已经被回收Java堆中不存在该类的任何实例。2. 加载该类的ClassLoader已经被回收。3. 该类对应的java.lang.Class对象没有在任何地方被引用无法在任何地方通过反射访问该类的方法。GC垃圾回收的原理判断出死亡的对象然后清除死亡的留下存活的。引用计数法Reference Counting可达性分析算法Reachability Analysis通过GC Roots对象线程栈变量、静态变量、常量池、JNI指针作为起始点然后从这些节点开始遍历所有引用链。如果某个对象没有GC Roots直接或间接连接的话这个对象就被认为程序中不再使用可以被回收了。垃圾回收的几种算法标记清除算法相对简单 存活对象比较多的情况下效率较高两遍扫描效率偏低 容易产生碎片标记复制适用于存活对象较少的情况只扫描一次效率提高没有碎片空间浪费移动复制对象需要调整对象引用标记压缩不会产生碎片方便对象分配不会产生内存减半扫描两次需要移动对象效率偏低程序计数寄存器Program Counter RegisterJVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。PC寄存器用来存储指向下一条指令的地址即将要执行的指令代码。由执行引擎读取下一条指令。在JVM规范中每个线程都有它自己的程序计数器是线程私有的生命周期与线程周期一致。每个线程在创建的时候都会创建一个虚拟机栈其内部保存一个个的栈帧Stack Frame对应一次次Java方法调用是线程私有的生命周期和线程一致。作用主管Java程序的运行它保存方法的局部变量部分结果并参与方法的调用和返回。Method AreaPerm Space (1.8) 字符串常量位于Perm Space FGC不会清理 大小启动的时候指定不能变Meta Space (1.8) 字符串常量位于堆 会触发FGC清理 不设定的话最大就是物理内存JVM内存分代模型用于分代垃圾回收算法部分垃圾回收器使用的模型除Epsilon ZGC Shenandoah之外的GC都是使用逻辑分代模型G1是逻辑分代物理不分代除此之外不仅逻辑分代而且物理分代MinorGC/YGC: 年轻代空间耗尽时触发MajorGC/FullGC: 在老年代无法继续分配空间时触发新生代老年代同时进行回收栈上分配线程私有小对象无逃逸支持标量替换无需调整线程本地分配TLAB (Thread Local Allocation Buffer)占用eden默认1%多线程的时候不用竞争eden就可以申请空间提高效率小对象无需调整对象分配过程垃圾回收器JDK1.8默认的垃圾回收PS ParallelOldSerial: a stop-the-world, copying collector which uses a single GC threadCMS的问题1. Memory Fragment2. Floating Garbage算法CMS算法三色标记 Incremental UpdateG1算法三色标记 SATBZGC算法ColoredPointers 写屏障Shenandoah算法ColoredPointers 读屏障调优系统CPU占用率100%一定有线程在占用系统资源找出哪个进程CPU高top该进程中的哪个线程CPU高top -Hp导出该线程的堆栈jstack查找哪个方法栈帧消耗时间jstack查找系统内存飚高问题导出堆内存jmap分析jhat, jvisualvm, mat, jprofiler ...三色标记白色未被标记的对象灰色自身被标记成员变量未被标记黑色自身和成员变量均已标记完成产生漏标1. 标记进行时增加了一个黑到白的引用如果不重新对黑色进行处理则会漏标2. 标记进行时删除了灰对象到白对象的引用那么这个白对象有可能被漏标1. incremental update: 增量更新关注引用的增加把黑色重新标记为灰色下次重新扫描属性CMS2. SATBsnapshot at the beginning:关注引用的删除 当引用消失时把这个引用推到GC的堆栈保证D还能被GC扫描到G1灰色 - 白色引用消失时如果没有黑色指向白色引用会被push到堆栈下次扫描时拿到这个引用由于有RSet的存在不需要扫描整个堆去查找指向白色的引用效率较高。CMS执行步骤初始标记、并发标记、重新标记、并发清理G1产生FGC怎么做1. 扩内存2. 提高CPU性能回收的快业务逻辑产生对象的速度固定垃圾回收越快内存空间越大3. 降低MixedGC触发的阈值让MixedGC提早发生默认是45%jps: 查看当前的系统中java的进程 拿到当前的进程号 PIDjinfo: 查看当前的java进程中的JVM参数的值jstat: 查看class信息查看gc的信息jstack: 查看当前线程的信息top: 查看CPU使用率jmap: 打印堆的存储快照jmap -dump:formatb,fileheap.hprof [PID] dump出堆内存相关的信息-XX:HeapDumpOnOutofMemoryError -XX:HeapDumpPathheap.hprof