# 1. OSGi 模块化的类加载机制 A OSGi 严格双亲委派,无模块隔离 B OSGi 只有一个类加载器 C OSGi 每个 bundle 有独立类加载器,按 Import/Export 声明进行委托,提供模块隔离与版本控制 ✓ 正确答案 D OSGi 不支持动态安装 bundle
# 2. 类加载的并行与并发(ClassLoader.loadClass 的锁) A 类加载不分锁,任何类都串行 B 并行类加载按类名细粒度加锁,不同类可并行加载,注册为 Parallel Capable 后生效 ✓ 正确答案 C 类加载无并发问题 D 所有自定义类加载器默认必须串行
# 3. 类加载器命名空间与同名类的隔离(跨加载器类型不匹配导致 ClassCastException) A 跨加载器转换永远成功 B 同名类由不同加载器加载后是同一个 Class 对象 C 类加载器只影响加载速度,不影响类型 D 类身份由类名 + 定义加载器共同决定,不同加载器加载同名类不兼容,跨加载器强转会抛 ClassCastException ✓ 正确答案
# 4. 线程上下文类加载器(TCCL)的应用场景 A TCCL 让父加载器能加载应用/第三方实现类,支持 JDBC、SPI 等打破双亲委派场景 ✓ 正确答案 B TCCL 只用于加载 JDK 内部类 C TCCL 与双亲委派无关 D TCCL 无法被修改
# 5. 运行时类卸载的条件(自定义类加载器可达性) A 只要类没有实例就能卸载,与加载器无关 B 类一旦加载永不卸载 C 类卸载只发生在 Full GC D 类卸载需该类、其 Class 对象及定义它的类加载器都不可达,类加载器被引用则类无法卸载 ✓ 正确答案
# 6. 双亲委派模型的打破场景,SPI(JDBC DriverManager)、Tomcat 隔离类加载如何实现? A 双亲委派绝对不可打破 B SPI 用 TCCL 让父加载子,Tomcat 逆序委派实现应用隔离,都是对双亲委派的必要打破 ✓ 正确答案 C JDBC 驱动必须由引导类加载器加载 D Tomcat 严格双亲委派,无隔离
# 7. 类加载过程与初始化时机,加载/验证/准备/解析/初始化的触发条件(主动/被动引用)如何? A 类初始化由主动引用触发(new、访问静态、反射等),被动引用(如引用常量、数组)不触发 ✓ 正确答案 B 任何类引用都会触发初始化 C 解析阶段才执行静态块 D 准备阶段就执行静态赋值
# 8. 自定义类加载器实现加密 class 加载与热部署的关键点 A 重写 findClass 读取并解密字节后 defineClass 实现加密加载,热部署用新类加载器替换并释放旧加载器 ✓ 正确答案 B 只需继承 ClassLoader 即可,无需重写方法 C 加密类无法被自定义加载器加载 D 热部署只需重新 new 一个类即可
# 9. 方法调用指令(invokevirtual/invokespecial/invokestatic/invokeinterface/invokedynamic)的语义差异 A invokestatic 用于调用虚方法 B invokedynamic 用于动态方法调用,由引导方法运行时解析,是 Lambda 的基础 ✓ 正确答案 C invokespecial 执行动态分派 D invokeinterface 只能调静态方法
# 10. java.lang.ClassLoader 的 defineClass 与 findClass 模板 A findClass 才是转换字节的入口,defineClass 无关 B 自定义加载器必须重写 loadClass 才能加载 C defineClass 不能返回 Class 对象 D defineClass 用于把字节数组转换为 Class 对象,自定义加载器重写 findClass 走双亲委派后加载 ✓ 正确答案
# 11. 字节码库(ASM/Javassist/ByteBuddy)选型 A ASM 底层高性能、API 复杂,Javassist 源码级简单、运行时开销大,ByteBuddy 高层易用兼顾性能 ✓ 正确答案 B ASM 简单易用,Javassist 性能最高 C 三者完全相同 D ByteBuddy 不能代理方法
# 12. 字节码指令集(aload/astore/iadd/invokevirtual 等) A aload 用于把整型存入局部变量表 B invokevirtual 用于调用静态方法 C 字节码基于操作数栈,aload/iload 加载数据、iadd 执行算术、invokevirtual 调用方法 ✓ 正确答案 D 字节码没有分支指令
# 13. 类文件结构(魔数、版本号、常量池、字段、方法、属性) A 类文件没有版本号 B 常量池只存字符串 C 字节码存在常量池中 D 类文件以 0xCAFEBABE 魔数开头,含版本号、常量池、字段/方法/属性表 ✓ 正确答案
# 14. JEP 484 与 ASM 在框架二次开发中的对比 A JEP 484 只能解析,不能生成 B ASM 是 JDK 内建 API C JEP 484 是 JDK 提供的 Class-File API,可解析/生成类文件,与成熟第三方库 ASM 相比更少依赖、API 更现代 ✓ 正确答案 D JEP 484 与字节码无关
# 15. 字节码增强的常见工具,ASM/Javassist/Byte Buddy 的 API 抽象层次对比如何? A 三者抽象层次完全相同 B ASM 是源码级、Byte Buddy 是指令级 C ASM 指令级底层高性能,Javassist 源码级简单但开销大,Byte Buddy 高层声明式易用且基于 ASM ✓ 正确答案 D Byte Buddy 无法生成子类
# 16. JVM 的类缓存与卸载,方法区 Metaspace 中的类何时被卸载? A 类只要无实例即可卸载 B 卸载与类加载器无关 C 类永远不会被卸载 D 类在以"类加载器 + 类"为单位、类加载器不可达时才会被卸载,Metaspace 据此回收 ✓ 正确答案
# 17. JVM 的运行时数据区与类元数据,Metaspace 的回收与 OOM 排查如何? A Metaspace 回收单个类,与加载器无关 B Metaspace 以类加载器为回收单元,OOM 常因类加载器泄漏或动态类过多,排查围绕类加载器引用与类加载频率 ✓ 正确答案 C Metaspace 永不 OOM D 元空间由 GC 自动回收,无需关注
# 18. JVM 栈帧(局部变量表/操作数栈)与方法调用的关系 A 每次方法调用创建一个栈帧,含局部变量表与操作数栈,方法返回时弹出销毁 ✓ 正确答案 B 操作数栈用来存方法参数 C 栈帧大小运行时动态无限增长 D 栈帧是全局共享的