编译器如何实现信息隐藏与封装?Java访问修饰符编译及JVM管控机制
Great question—let’s break this down step by step, since it cuts to the core of how Java enforces encapsulation at both compile time and runtime.
Encapsulation in Java isn’t just a coding convention—it’s enforced by two key players: the compiler and the JVM. The private, public, and protected modifiers act as metadata tags that tell these tools which parts of a class are off-limits to external code.
At its core, information hiding works by restricting access to a class’s internal state (fields) and helper methods, forcing external code to interact with the class only through its public API. This prevents unintended side effects and makes code easier to maintain.
private and public Members When you compile your Bowel class, the compiler adds access flags to each field and method in the generated bytecode. These flags are the JVM’s way of knowing the access level of each member.
If you run javap -v Bowel.class (a tool that disassembles bytecode), you’ll see clear differences between your two fields:
For the public field:
public com.example.Movement publicPoop; descriptor: Lcom/example/Movement; flags: (0x0001) ACC_PUBLIC
For the private field:
private com.example.Movement privatePoop; descriptor: Lcom/example/Movement; flags: (0x0002) ACC_PRIVATE
The only meaningful difference here is the flags value: ACC_PUBLIC (0x0001) vs ACC_PRIVATE (0x0002). The rest of the field metadata (like its type) is identical. These flags are critical—they’re what the JVM uses to enforce access rules at runtime.
Let’s walk through what happens when external code tries to access privatePoop:
1. Compile-Time Check (First Line of Defense)
If you write code like this outside the Bowel class:
Bowel myBowel = new Bowel(); Movement poop = myBowel.privatePoop; // Trying to access private field
The compiler will immediately throw an error: error: privatePoop has private access in Bowel. It won’t even generate bytecode for this invalid code. This is the compiler enforcing the language’s access rules before your code ever runs.
2. Runtime Check (Safety Net)
What if someone tries to bypass the compiler—say, using reflection to access the private field? By default, the JVM will still block this. When you use reflection to get or set a private field without explicitly enabling access, the JVM checks the field’s ACC_PRIVATE flag and throws an IllegalAccessException.
You can bypass this with field.setAccessible(true), but that’s an intentional override (and usually a code smell, unless you’re doing something like serialization or testing). The JVM still enforces the access rule unless you explicitly tell it not to.
内容的提问来源于stack exchange,提问作者Anwar Hahj Jefferson-George

