目录Java 内存区域JVM 哪个内存区域不会发生 OutOfMemoryErrorOOM字符串常量池的作用是JVM 垃圾回收如何判断对象是否死亡垃圾回收算法问题排查Java 内存区域Java 内存区域指的是 JVM 在执行 Java 程序时把内存划分成的不同功能区域。线程私有区域每个线程独立程序计数器PC Register记录当前线程执行到哪一条字节码。虚拟机栈JVM Stack存储方法执行过程栈帧。本地方法栈Native Stack执行 native 方法C/C。线程共享区域所有线程共享堆Heap存放所有对象实例。方法区Method Area类信息、静态变量、常量池、方法字节码。JDK 1.8 变化重点方法区实现变成元空间Metaspace不在 JVM 内存而是使用本地内存Native Memory。JVM 哪个内存区域不会发生 OutOfMemoryErrorOOM程序计数器。程序计数器用于记录当前线程执行的字节码指令位置通过改变计数器的值来控制程序的流程执行包括顺序执行、分支、循环和异常处理等。在多线程环境下每个线程都需要独立的程序计数器用于记录各自的执行位置从而在线程切换后能够恢复到正确的执行状态。由于程序计数器占用内存极小、生命周期随线程创建和销毁而变化并且不涉及动态内存分配因此不会发生内存溢出。字符串常量池的作用是字符串常量池是 JVM 为了提升性能和减少内存消耗为字符串专门开辟的一块区域用于存储字符串字面量避免重复创建相同内容的字符串对象。当创建字符串时如果常量池中已存在该字符串则直接返回引用否则将其加入常量池。JVM 垃圾回收如何判断对象是否死亡可达性分析算法。从 GC Roots 出发向下搜索可达对象。如果一个对象无法通过引用链从 GC Roots 访问到就认为它“死亡”。GC Roots 主要包括虚拟机栈中的局部变量、本地方法栈中的引用、方法区中的静态变量和常量、被同步锁持有的对象以及 JNI 引用等。即使对象在可达性分析中不可达也不会立即被回收而是会经历一次标记和筛选过程只有在无法重新建立引用关系时才会被真正回收。Q为什么引用计数法不被采用A因为无法解决循环引用问题会导致内存泄漏。QGC Roots 为什么要这些对象A因为它们处于程序运行核心路径中代表“正在使用”的对象。Q对象一定会被 GC 回收吗A不一定需要经历可达性分析 finalize 筛选。垃圾回收算法1标记-清除算法Mark-Sweep分两步标记存活对象清除未标记对象缺点效率低、产生内存碎片。2复制算法Copying将内存一分为二只用一半From区 → To区存活对象复制。优点没有内存碎片、分配速度快、适合新生代。缺点浪费内存50% 内存被闲置、对象存活多时效率低复制成本极高。3标记-整理算法Mark-Compact分三步标记存活对象向一端移动存活对象清理边界外空间优点没有碎片、内存利用率高。缺点移动对象成本高。4分代收集算法现代主流思想不同生命周期对象采用不同算法。新生代Young对象“死得快”、存活率低适合复制算法。老年代Old对象存活率高、回收频率低适合标记-整理。问题排查内存问题OOM、泄漏线程问题死锁、阻塞性能问题CPU过高、GC频繁Java 性能优化和问题排查工具主要分为三类。第一类是 JDK 自带的可视化工具例如 JConsole 和 VisualVM可以用于监控 JVM 的内存、线程、GC 等运行状态其中 VisualVM 功能更强大还支持 Heap Dump 分析。第二类是 JDK 命令行工具包括 jps 用于查看 Java 进程jstat 用于监控 GC 状态jmap 用于生成堆内存快照jstack 用于查看线程栈信息排查死锁问题。第三类是第三方工具例如 MAT 用于分析 Heap Dump定位内存泄漏GCViewer 和 GCeasy 用于分析 GC 日志JProfiler 用于性能分析Arthas 是阿里开源的线上诊断工具可以在不重启应用的情况下实时查看线程、内存和方法调用情况。在实际排查中如果发生死锁可以通过 jstack 查看线程栈通常会出现 Found one Java-level deadlock 字样如果发生 OutOfMemoryError可以通过 jmap 导出 Heap Dump再用 MAT 分析内存泄漏问题。Q线上 CPU 100% 怎么排查Atop 找进程 → jstack 找线程 → 定位死循环或锁竞争