拿到一个第三方 jar 包想改一行逻辑,解压出来全是 .class,用记事本打开是一堆乱码。这类文件不是加密,而是编译之后的字节码。
它是 Java 源码的编译产物
javac Hello.java 之后生成的 Hello.class,里面是 JVM 能直接执行的字节码指令,文件头魔数是 0xCAFEBABE。它不是给人看的,所以文本编辑器打开只有方块和乱码。JDK 9 之后还会多出一个模块描述符 module-info.class。
看字节码的正确工具
先用 javap -c -p Hello.class 反汇编,能看到常量池、方法签名和指令序列。想看源码就得靠反编译器,JD-GUI、CFR、Procyon 都能把 class 还原成近似 Java 代码。注意反编译结果只是相似,变量名可能变成 var1、var2 这类占位名。
运行时 class 从哪来
- 目录方式:直接用 java 命令运行指定目录下的 class,classpath 要指对。
- jar 方式:jar 就是一堆 class 加 META-INF 下的清单文件打包而成。
- war 方式:Web 项目的 class 放在 WEB-INF/classes 目录下。
- 内存加载:框架用自定义 ClassLoader 从字节数组直接定义类,磁盘上不一定有文件。
版本号对不上是最常见的坑
class 文件里记着 major version,Java 8 是 52,Java 11 是 55,Java 17 是 61。用低版本 JDK 跑高版本编译的 class,会报 UnsupportedClassVersionError 加一串数字。看到这个错误别怀疑代码,先核对 javac 和 java 的版本,或者加参数按目标版本重新编译。另外 class 之间是二进制兼容的,改了一个方法签名,调用它的那个 class 也得重编。