Java访问修饰符存储于.class文件的access flags中,javap -p可查看private及默认成员,JD-GUI等工具据此还原关键字,反射API则通过Modifier类动态解析标志位。

Java 中访问修饰符本身不直接“存储”在源码里,而是编译进 .class 文件的结构中,作为类、字段或方法的访问标志(access flags)。反编译工具的作用,就是解析这些二进制标志,并以人类可读的方式还原出 public、private、protected 或默认(package-private)等修饰信息。
javap 是最直接查看访问标志的命令行工具
javap 是 JDK 自带的类文件分析器,它不还原完整 Java 源码,但能准确展示每个成员的访问修饰符对应的实际标志位。关键在于使用 -p(即 --private)选项:
-
javap -p ClassName:强制显示所有成员,包括private和default级别的字段与方法 -
javap -v ClassName:输出详细信息,含常量池、属性表及每项的Access Flags字段(如public、final、synthetic) - 对比不同选项:
-public只列public成员,-protected包含protected和public,而-p是唯一能看到private和包级私有成员的方式
图形化工具(如 JD-GUI、IDEA)会自动推断并高亮修饰符
JD-GUI、IntelliJ IDEA 内置反编译器等图形工具,底层也解析 class 文件的 access flags,再按 Java 语法习惯渲染成带关键字的伪源码:
- 它们能识别
ACC_PRIVATE标志,并在反编译结果中补上private关键字(即使原始源码没写,或被混淆器移除) - 对默认访问(无修饰符)的字段/方法,工具通常不加任何关键字,但可通过上下文(如是否跨包调用失败)辅助判断
- 注意:某些混淆后的 class 文件可能人为篡改标志位,导致工具误判;此时需结合
javap -v查看原始 flag 值(如0x0002表示private)交叉验证
通过反射 API 动态检查访问修饰符
运行时也可获取访问标志,原理与 javap 一致,都是读取 class 文件元数据:
立即学习“Java免费学习笔记(深入)”;
-
Class.getModifiers()返回一个整型值,是多个修饰符标志的按位或结果 - 用
Modifier.isPublic()、Modifier.isPrivate()等静态方法解码,比手动查二进制更安全可靠 - 例如:
field.getModifiers()对应字段的访问控制,method.getModifiers()对应方法——这和javap -p输出的字段/方法列表一一对应
理解访问标志的实际含义比关键字更重要
反编译看到的 public 不代表“一定能调用”,还需结合运行时环境:
- 一个
public static final字段,在javap -c中可能被内联为常量,反编译后甚至不出现该字段引用 -
protected方法在不同包子类中可访问,但javap只显示标志,不校验继承关系;工具渲染出的代码能否编译通过,取决于实际类路径和包结构 - 默认(package-private)成员在
javap -p中可见,但在其他包中直接 new 实例或调用会编译失败——这是访问修饰符语义的体现,不是反编译缺陷


















