类加载与字节码

共 18 题
#

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 栈帧是全局共享的