JVM内存模型1、线程私有1.1、Java虚拟机栈Java方法执行的内存模型生命周期与线程相同执行时创建栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等局部变量量表存放编译器可知的各种基本数据类型、对象引用和returnAddress类型操作数栈存放要操作的数动态连接对应代码内存入口地址方法出口方法调用或异常返回地址对象引用对象存储在Java堆中这里存的时对象的引用1.2、本地方法栈native修饰的方法private native void start0();1.3、程序计数器当执行Java方法时正在执行的虚拟机字节码地址当执行Native方法时Undefined2、共享区域2.1、Java堆存放对象实例GC的主要区域。新生代、老年代。Eden区、From Surivivor区、To Surivivor区。8112.2、方法区用于存储已被虚机加载的类信息、常量、静态变量、即时编译器编译后的代码等。3、异常运行时数据区对应异常数据区StackOverflowErrorOutOfMemoryError方法区NA方法区无法满足内存分配需求时Java堆NA堆中没有内存完成实例分配并且堆也无法再扩展时虚拟机栈线程请求的栈深度大于虚机所允许的深度时扩展时无法申请到足够的内存时本地方法栈线程请求的栈深度大于虚机所允许的深度时扩展时无法申请到足够的内存时程序计数器NANA垃圾回收1、GC RootsJVM中被称为GC Roots的对象是指垃圾回收器在进行可达性分析时作为起始节点的“活跃”对象。凡是通过直接或间接引用链能够与 GC Roots 相连的对象都会被判定为“存活”反之则被视为垃圾等待回收。在Java中以下6种类型的对象通常可以作为 GC Roots虚拟机栈引用的对象当前正在执行的方法中使用的局部变量表、参数和临时对象。本地方法栈引用的对象在调用 Native 方法使用 C/C 等编写的代码时引用的对象。方法区中静态属性引用的对象类变量即被static关键字修饰的对象引用。方法区中常量引用的对象字符串常量池里的引用或被final修饰的常量。同步锁持有的对象被synchronized关键字锁住的对象。JNI 句柄引用的对象通过 Java Native Interface 引用的本地对象。2、对象是否存活2.1、引用计数器算法给对象添加一个引用计数器每当有一个地方引用它时计数器值就1当引用失效时计数器就-1当计数器值为0时对象就不再被使用缺陷当出现对象相互循环引用时永远不会被回收2.2、可达性分析算法2.3、引用2.3.1、强引用只要强引用存在垃圾回收器绝对不会回收被引用的对象。Object obj new Object();2.3.2、软引用只有当 JVM内存不足即将抛出 OOM 前垃圾回收器才会将这些对象列入回收范围进行二次回收。String str new String(abc); SoftReferenceString reference new SoftReference(str);2.3.3、弱引用比软引用更弱。无论内存是否充足只要垃圾回收器运行只要发现只被弱引用关联的对象就会立即回收。String str new String(abc); WeakReferenceString reference new WeakReference(str);2.3.4、虚引用任何时候都可能被垃圾回收器回收String str new String(abc); ReferenceQueue queue new ReferenceQueue(); // 创建虚引用要求必须与一个引用队列关联 PhantomReferenceString reference new PhantomReference(str, queue);3、垃圾收集算法算法优点弊端标记-清除算法基础算法实现简单不需要移动对象1、标记和清除2个效率都不高2、空间不连续空间碎片复制算法不会产生内存碎片浪费一半的空间标记-整理算法1、不会产生内存碎片2、内存利用率高在移动对象时必须STW分代收集算法资源利用率高针对不同区域采用最合适的算法如新生代用复制算法老年代用标记-整理算法算法逻辑相对复杂4、垃圾收集器JVM 垃圾收集器主要分为分代收集器如 Parallel、CMS、G1和全功能/并发收集器如 ZGC。不同收集器的优缺点决定了其应用场景追求高吞吐量选 Parallel追求低延迟选 CMS 或 G1追求超大内存/极致低延迟选 ZGC。常见垃圾收集器优缺点收集器名称工作区域优点缺点Serial / Serial Old新生代 / 老年代单线程内存消耗小没有线程交互开销。GC 时需暂停所有用户线程STW垃圾回收时间长。Parallel Scavenge / Parallel Old新生代 / 老年代多线程并行回收追求高吞吐量CPU利用率高。GC 停顿时间较长不适合强交互的低延迟应用。CMS(Concurrent Mark Sweep)老年代并发收集、低停顿用户线程与 GC 线程同时执行。产生内存碎片对 CPU 资源敏感无法处理“浮动垃圾”。G1(Garbage-First)全堆分代管理可预测停顿时间将堆内存划分为多个 Region避免了全区碎片化。内存占用高程序运行时的负载与复杂度较高。ZGC(Z Garbage Collector)全堆不分代/自适应超低延迟停顿 10ms支持超大堆数 TB几乎不受堆大小影响。吞吐量相比 Parallel 略低处于持续演进中。5、内存分配和回收策略JVM参数JVM参数主要分为标准参数-、非标准参数-X和不稳定参数-XX。合理配置这些参数能够显著提升应用程序的性能、内存管理与故障排查效率。以下为您整理了生产环境中必不可少的常用JVM参数分类清单。1、 堆内存与非堆内存配置控制Java应用运行时的内存分配是性能调优的第一步。-Xms设置JVM启动时的初始堆内存建议与-Xmx一致避免内存抖动。-Xmx设置JVM最大可用堆内存。-Xmn设置年轻代Young Generation的大小。-XX:MetaspaceSize设置元空间Metaspace的初始大小触发首次Full GC的阈值。-XX:MaxMetaspaceSize限制元空间的最大大小防止内存泄漏耗尽系统内存。-XX:SurvivorRatio设置Eden区与单个Survivor区的大小比例如8表示Eden:S0:S1 8:1:1。2、 垃圾收集器GC策略根据业务场景选择合适的GC算法以平衡吞吐量和停顿时间。-XX:UseParallelGCJDK 8 默认的并行GC注重吞吐量。-XX:UseG1GCJDK 9及之后版本的默认GC兼顾吞吐量与低延迟。-XX:UseZGC适用于超大堆内存、需要极低延迟亚毫秒级的现代应用。-XX:MaxGCPauseMillis在使用G1或ZGC时设置期望的最大GC停顿时间。3、 异常与故障排查在生产环境发生OOM内存溢出时通过这些参数留存现场数据。-XX:HeapDumpOnOutOfMemoryError当首次发生OOM时自动生成 Heap Dump 内存快照文件。-XX:HeapDumpPath指定 Heap Dump 文件的生成路径和文件名。-XX:ErrorFile指定JVM致命错误日志如 Crash 日志的存储路径。4、 GC日志记录记录详细的GC运行情况用于排查内存泄漏及优化GC停顿。-Xlog:gc*(JDK 9)开启统一的GC日志记录输出详细信息。-XX:PrintGCDetails(JDK 8及以下)打印详细的GC日志信息。-Xloggc(JDK 8及以下)指定GC日志的输出文件路径。5、 其他常用优化参数-XX:DisableExplicitGC屏蔽业务代码中显式的System.gc()调用防止引发人为的Full GC。-Xss设置每个线程的栈内存大小例如512k决定了函数调用的最大深度。-XX:UseStringDeduplication启用字符串去重优化存在大量重复字符串的应用内存占用Java 8u20及以上支持。优化实战1、双11亿级电商网站JVM参数调优2、单机几十万并发的系统JVM调优虚拟机类加载机制1、类加载器1.1、类加载的时机类从被加载到虚拟机内存中开始到卸载出内存为止整个生命周期包括5个阶段加载连接验证 准备 解析初始化使用卸载1.2、类加载器BootstrapClassLoader启动类加载器加载JAVA_HOME\lib目录下或者被-Xbootclasspath参数所指定的路径下并且是虚拟机识别的类库加载到虚拟机内存中ExtClassLoader扩展类加载器加载JAVA_HOME\lib\ext目录下或者被java.ext.dirs系统变量所指定的类库开发者可以直接使用ExtClassLoader加载器由sun.misc.Launcher$ExtClassLoader实现AppClassLoader应用程序加载器也叫系统类加载器加载器由sun.misc.Launcher$ExtClassLoader实现开发者可以直接使用AppClassLoaderUserClassLoader1.3、JDK双亲委派机制每个类加载器对加载过的类有缓存向上委托查找向下委托加载
Java虚拟机JVM
JVM内存模型1、线程私有1.1、Java虚拟机栈Java方法执行的内存模型生命周期与线程相同执行时创建栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等局部变量量表存放编译器可知的各种基本数据类型、对象引用和returnAddress类型操作数栈存放要操作的数动态连接对应代码内存入口地址方法出口方法调用或异常返回地址对象引用对象存储在Java堆中这里存的时对象的引用1.2、本地方法栈native修饰的方法private native void start0();1.3、程序计数器当执行Java方法时正在执行的虚拟机字节码地址当执行Native方法时Undefined2、共享区域2.1、Java堆存放对象实例GC的主要区域。新生代、老年代。Eden区、From Surivivor区、To Surivivor区。8112.2、方法区用于存储已被虚机加载的类信息、常量、静态变量、即时编译器编译后的代码等。3、异常运行时数据区对应异常数据区StackOverflowErrorOutOfMemoryError方法区NA方法区无法满足内存分配需求时Java堆NA堆中没有内存完成实例分配并且堆也无法再扩展时虚拟机栈线程请求的栈深度大于虚机所允许的深度时扩展时无法申请到足够的内存时本地方法栈线程请求的栈深度大于虚机所允许的深度时扩展时无法申请到足够的内存时程序计数器NANA垃圾回收1、GC RootsJVM中被称为GC Roots的对象是指垃圾回收器在进行可达性分析时作为起始节点的“活跃”对象。凡是通过直接或间接引用链能够与 GC Roots 相连的对象都会被判定为“存活”反之则被视为垃圾等待回收。在Java中以下6种类型的对象通常可以作为 GC Roots虚拟机栈引用的对象当前正在执行的方法中使用的局部变量表、参数和临时对象。本地方法栈引用的对象在调用 Native 方法使用 C/C 等编写的代码时引用的对象。方法区中静态属性引用的对象类变量即被static关键字修饰的对象引用。方法区中常量引用的对象字符串常量池里的引用或被final修饰的常量。同步锁持有的对象被synchronized关键字锁住的对象。JNI 句柄引用的对象通过 Java Native Interface 引用的本地对象。2、对象是否存活2.1、引用计数器算法给对象添加一个引用计数器每当有一个地方引用它时计数器值就1当引用失效时计数器就-1当计数器值为0时对象就不再被使用缺陷当出现对象相互循环引用时永远不会被回收2.2、可达性分析算法2.3、引用2.3.1、强引用只要强引用存在垃圾回收器绝对不会回收被引用的对象。Object obj new Object();2.3.2、软引用只有当 JVM内存不足即将抛出 OOM 前垃圾回收器才会将这些对象列入回收范围进行二次回收。String str new String(abc); SoftReferenceString reference new SoftReference(str);2.3.3、弱引用比软引用更弱。无论内存是否充足只要垃圾回收器运行只要发现只被弱引用关联的对象就会立即回收。String str new String(abc); WeakReferenceString reference new WeakReference(str);2.3.4、虚引用任何时候都可能被垃圾回收器回收String str new String(abc); ReferenceQueue queue new ReferenceQueue(); // 创建虚引用要求必须与一个引用队列关联 PhantomReferenceString reference new PhantomReference(str, queue);3、垃圾收集算法算法优点弊端标记-清除算法基础算法实现简单不需要移动对象1、标记和清除2个效率都不高2、空间不连续空间碎片复制算法不会产生内存碎片浪费一半的空间标记-整理算法1、不会产生内存碎片2、内存利用率高在移动对象时必须STW分代收集算法资源利用率高针对不同区域采用最合适的算法如新生代用复制算法老年代用标记-整理算法算法逻辑相对复杂4、垃圾收集器JVM 垃圾收集器主要分为分代收集器如 Parallel、CMS、G1和全功能/并发收集器如 ZGC。不同收集器的优缺点决定了其应用场景追求高吞吐量选 Parallel追求低延迟选 CMS 或 G1追求超大内存/极致低延迟选 ZGC。常见垃圾收集器优缺点收集器名称工作区域优点缺点Serial / Serial Old新生代 / 老年代单线程内存消耗小没有线程交互开销。GC 时需暂停所有用户线程STW垃圾回收时间长。Parallel Scavenge / Parallel Old新生代 / 老年代多线程并行回收追求高吞吐量CPU利用率高。GC 停顿时间较长不适合强交互的低延迟应用。CMS(Concurrent Mark Sweep)老年代并发收集、低停顿用户线程与 GC 线程同时执行。产生内存碎片对 CPU 资源敏感无法处理“浮动垃圾”。G1(Garbage-First)全堆分代管理可预测停顿时间将堆内存划分为多个 Region避免了全区碎片化。内存占用高程序运行时的负载与复杂度较高。ZGC(Z Garbage Collector)全堆不分代/自适应超低延迟停顿 10ms支持超大堆数 TB几乎不受堆大小影响。吞吐量相比 Parallel 略低处于持续演进中。5、内存分配和回收策略JVM参数JVM参数主要分为标准参数-、非标准参数-X和不稳定参数-XX。合理配置这些参数能够显著提升应用程序的性能、内存管理与故障排查效率。以下为您整理了生产环境中必不可少的常用JVM参数分类清单。1、 堆内存与非堆内存配置控制Java应用运行时的内存分配是性能调优的第一步。-Xms设置JVM启动时的初始堆内存建议与-Xmx一致避免内存抖动。-Xmx设置JVM最大可用堆内存。-Xmn设置年轻代Young Generation的大小。-XX:MetaspaceSize设置元空间Metaspace的初始大小触发首次Full GC的阈值。-XX:MaxMetaspaceSize限制元空间的最大大小防止内存泄漏耗尽系统内存。-XX:SurvivorRatio设置Eden区与单个Survivor区的大小比例如8表示Eden:S0:S1 8:1:1。2、 垃圾收集器GC策略根据业务场景选择合适的GC算法以平衡吞吐量和停顿时间。-XX:UseParallelGCJDK 8 默认的并行GC注重吞吐量。-XX:UseG1GCJDK 9及之后版本的默认GC兼顾吞吐量与低延迟。-XX:UseZGC适用于超大堆内存、需要极低延迟亚毫秒级的现代应用。-XX:MaxGCPauseMillis在使用G1或ZGC时设置期望的最大GC停顿时间。3、 异常与故障排查在生产环境发生OOM内存溢出时通过这些参数留存现场数据。-XX:HeapDumpOnOutOfMemoryError当首次发生OOM时自动生成 Heap Dump 内存快照文件。-XX:HeapDumpPath指定 Heap Dump 文件的生成路径和文件名。-XX:ErrorFile指定JVM致命错误日志如 Crash 日志的存储路径。4、 GC日志记录记录详细的GC运行情况用于排查内存泄漏及优化GC停顿。-Xlog:gc*(JDK 9)开启统一的GC日志记录输出详细信息。-XX:PrintGCDetails(JDK 8及以下)打印详细的GC日志信息。-Xloggc(JDK 8及以下)指定GC日志的输出文件路径。5、 其他常用优化参数-XX:DisableExplicitGC屏蔽业务代码中显式的System.gc()调用防止引发人为的Full GC。-Xss设置每个线程的栈内存大小例如512k决定了函数调用的最大深度。-XX:UseStringDeduplication启用字符串去重优化存在大量重复字符串的应用内存占用Java 8u20及以上支持。优化实战1、双11亿级电商网站JVM参数调优2、单机几十万并发的系统JVM调优虚拟机类加载机制1、类加载器1.1、类加载的时机类从被加载到虚拟机内存中开始到卸载出内存为止整个生命周期包括5个阶段加载连接验证 准备 解析初始化使用卸载1.2、类加载器BootstrapClassLoader启动类加载器加载JAVA_HOME\lib目录下或者被-Xbootclasspath参数所指定的路径下并且是虚拟机识别的类库加载到虚拟机内存中ExtClassLoader扩展类加载器加载JAVA_HOME\lib\ext目录下或者被java.ext.dirs系统变量所指定的类库开发者可以直接使用ExtClassLoader加载器由sun.misc.Launcher$ExtClassLoader实现AppClassLoader应用程序加载器也叫系统类加载器加载器由sun.misc.Launcher$ExtClassLoader实现开发者可以直接使用AppClassLoaderUserClassLoader1.3、JDK双亲委派机制每个类加载器对加载过的类有缓存向上委托查找向下委托加载