核心是用setAccessible(true)临时绕过访问检查,而非破坏安全机制;需先getDeclaredMethod获取私有方法,再调用setAccessible(true),最后invoke执行;注意Java 9+模块限制、SecurityManager拒绝及性能影响。

Java 反射中调用私有方法,核心就是用 setAccessible(true) 临时绕过 Java 的访问控制检查。这不是“破坏”安全机制,而是反射设计时就预留的调试和框架支持能力——但仅在运行时生效,不影响编译和字节码校验。
获取私有方法并设为可访问
先通过 getDeclaredMethod 获取目标私有方法(注意不能用 getMethod,它只查 public 方法),再立刻调用 setAccessible(true):
Class<?> clazz = MyClass.class;
Method privateMethod = clazz.getDeclaredMethod("doSecretWork", String.class);
privateMethod.setAccessible(true); // 关键一步:关闭访问检查
⚠️ 注意:setAccessible(true) 只对当前 Method 对象生效,不改变类定义,也不影响其他反射对象。
调用私有方法
设为可访问后,即可用 invoke 正常调用,传入目标实例(静态方法传 null)和参数:
使用tbot机器ID身份文件配合tsh CLI,通过Teleport访问控制SSH登录托管主机或执行远程命令。
立即学习“Java免费学习笔记(深入)”;
MyClass instance = new MyClass(); Object result = privateMethod.invoke(instance, "hello");
如果方法是 static,第一个参数写 null 即可;若抛 IllegalAccessException,说明漏了 setAccessible(true)。
常见注意事项
- Java 9+ 模块系统下,若类在非开放模块中,可能触发
InaccessibleObjectException,需在 JVM 启动时加参数:--add-opens java.base/java.lang=ALL-UNNAMED(根据实际包调整) -
setAccessible(true)在安全管理器(SecurityManager)启用时可能被拒绝,生产环境通常禁用该 API - 频繁使用反射 + setAccessible 会影响性能,JIT 可能无法有效优化,建议缓存
Method对象 - 单元测试或框架内部常用,业务代码中应优先考虑设计重构(如改用 package-private 或提供测试友好的 public 接口)
替代思路(更安全)
不是所有场景都必须硬闯私有方法:
- 把方法改为
package-private(默认访问级别),同一包下的测试类可直接调用 - 为测试暴露一个
@VisibleForTesting的 public 包装方法(配合注释说明用途) - 用 Mockito 等框架 mock 行为,而非真实调用私有逻辑

















