| 问题 | 关键词/关键概念 |
| ---------------------------- | ------------------------------------------------------------------------------------------------- |
| YoungGC和FullGC触发条件?| YoungGC:Eden满、FullGC:老年代满、Metaspace满、System.gc()、晋升失败 |
| FullGC多久一次算正常?| 取决于业务、几小时到几天、频繁FullGC需优化、监控老年代增长速度 |
| G1和CMS有什么区别?| G1分Region可预测停顿、CMS标记清除碎片化、G1整体标记整理局部复制、CMS低延迟G1可控延迟 |
| | |
| | |
| JDK 11中ZGC特点?| 超低延迟<10ms、TB级堆、并发处理、着色指针、读屏障、Region动态大小 |
| JDK1.8和1.9类加载器不同?| JDK9模块化、BootstrapClassLoader变BootClassLoader、ExtClassLoader变PlatformClassLoader、URLClassLoader非父类 |
| JVM完整GC流程?| MinorGC触发→标记存活→复制到Survivor/晋升→MajorGC→并发标记→回收→压缩整理 |
| JVM为什么区分堆和栈?| 生命周期不同、堆存对象栈存局部变量、堆共享栈线程私有、内存管理策略不同 |
| JVM如何保证分配内存线程安全?| TLAB线程本地分配缓冲、CAS+失败重试、分配指针同步 |
| JVM如何判断对象存活?| 可达性分析、GC Roots(栈、方法区、本地方法栈、系统类)、引用链 |
| JVM如何创建对象?| 类加载检查→分配内存→初始化零值→设置对象头→执行init方法 |
| JVM垃圾回收算法?| 标记清除、标记复制、标记整理、分代收集、增量收集 |
| JVM运行时内存区域?| 堆、方法区、虚拟机栈、本地方法栈、程序计数器、直接内存 |
| Java 8和Java 11的GC区别?| Java8默认Parallel、Java11默认G1、新增ZGC和Shenandoah、CMS被废弃 |
| Java一定平台无关吗?| 不一定、JNI本地代码、操作系统API、文件路径分隔符、换行符 |
| 对象一定在堆上分配吗?| 不一定、逃逸分析、标量替换、栈上分配、TLAB |
| 类什么时候被加载?| new实例化、访问静态成员、反射、子类加载、main方法类、MethodHandle |
| 类加载过程?| 加载→验证→准备→解析→初始化→使用→卸载 |
| OOM一定导致JVM退出吗?| 不一定、线程OOM不影响其他线程、OutOfMemoryError可catch、-XX:OnOutOfMemoryError |
| Java如何实现平台无关?| 字节码、JVM屏蔽差异、标准API、Write Once Run Anywhere |
| Java编译型还是解释型?| 混合型、javac编译成字节码、解释执行+JIT编译热点代码 |
| 堆如何分代?为什么?| 新生代(Eden+2Survivor)老年代、对象生命周期不同、分代假设、不同GC策略 |
| OutOfMemory和StackOverflow区别?| OOM堆/方法区内存不足、SOF栈深度超限、Error类型、内存区域不同 |
| Java进程占用内存?| 堆、线程栈、方法区、直接内存、JVM自身、代码缓存、Socket缓冲区 |
| 对象结构?| 对象头(Mark Word+类型指针)、实例数据、对齐填充 |
| 为什么G1成为JDK9默认GC?| 可预测停顿、大堆支持、并发标记、增量式回收、更好的吞吐量延迟平衡 |
| 为什么初始/重新标记需STW?| 保证一致性快照、避免漏标、标记GC Roots、处理并发标记期间变化 |
| 什么情况JVM退出?| 正常结束、System.exit()、Runtime.halt()、未捕获异常、kill信号、致命错误 |
| 什么是AOT编译?| Ahead-Of-Time提前编译、编译成机器码、启动快内存少、JIT运行时编译优化更好 |
| Class常量池vs运行时常量池?| Class常量池在字节码中、运行时常量池在方法区、类加载时转换、动态性 |
| 什么是STW?影响?| Stop-The-World、暂停应用线程、延迟增加、影响响应时间、吞吐量降低 |
| 什么是safe point?| 安全点、线程状态一致位置、方法调用、循环跳转、异常跳转处 |
| 什么是三色标记算法?| 白色未标记、灰色已标记未扫描、黑色已标记已扫描、增量标记基础 |
| 什么是双亲委派?如何破坏?| 向上委托加载、避免重复、保证核心类安全、重写loadClass、线程上下文类加载器、OSGi |
| 什么是堆外内存?| DirectByteBuffer、NIO使用、不受GC管理、零拷贝、-XX:MaxDirectMemorySize |
| 强软弱虚引用?| 强引用不回收、软引用内存不足回收、弱引用下次GC回收、虚引用跟踪回收 |
| 什么是方法区?实现?| 存储类元数据、JDK7前永久代、JDK8后Metaspace、使用本地内存 |
| 什么是编译和反编译?| 编译源码→字节码、反编译字节码→源码、javac编译、javap反编译 |
| 什么是跨代引用?| 新生代对象引用老年代、老年代引用新生代、记忆集RememberedSet、卡表CardTable |
| 什么是逃逸分析?| 分析对象作用域、方法逃逸、线程逃逸、栈上分配、标量替换、锁消除 |
| CMS垃圾回收过程?| 初始标记STW→并发标记→重新标记STW→并发清除→并发重置 |
| 内存泄漏vs内存溢出?| 泄漏无法回收持续增长、溢出超出限制、泄漏导致溢出、长生命周期持有短生命周期 |
| 哪些语言有GC?| Java、Python、C#、Go、Ruby、JavaScript、Rust(不同机制) |
| 如何判断同一个类?| 类全限定名相同、同一个ClassLoader加载、包名+类名+加载器 |
| 字符串常量池实现?| StringTable哈希表、JDK7移至堆、intern()方法、去重机制 |
| kill -9对JDK进程影响?| 强制终止、无法执行关闭钩子、资源未释放、数据丢失风险 |
| 常见JVM工具?| jps、jstat、jmap、jstack、jconsole、jvisualvm、jcmd、jhsdb |
| 新生代老年代GC算法?| 新生代复制算法、老年代标记清除/标记整理、分代收集 |
| 新生代老年代GC区别?| 新生代频繁快速复制、老年代低频慢速标记整理、对象特点不同 |
| 只有Eden+1个Survivor可以吗?| 不可以、需要2个Survivor交替使用、避免碎片、保证连续空间 |
| 常用JVM启动参数?| -Xms/-Xmx堆大小、-XX:NewRatio新生代比例、-XX:+UseG1GC、-XX:MaxGCPauseMillis |
| 破坏双亲委派能重写String吗?| 不能、启动类加载器预加载、安全管理器限制、JVM内部检查 |
| JIT优化技术?| 方法内联、逃逸分析、公共子表达式消除、数组边界检查消除、循环展开 |
| 类生命周期?| 加载→连接(验证准备解析)→初始化→使用→卸载 |
| 堆一定线程共享吗?| 主要共享、TLAB线程私有、分配缓冲区提高效率 |
| 并发回收vs并行回收?| 并发与应用线程同时、并行多GC线程、并发低延迟、并行高吞吐 |
| 运行时常量池vs字符串常量池?| 运行时常量池每个类一份、字符串常量池全局唯一、后者是前者一部分 |
| 如何选择垃圾回收器?| 延迟敏感ZGC/G1、吞吐量优先Parallel、堆大小、停顿要求、硬件资源 |