如何获取运行中JVM内java.security.Security的所有属性当前状态
如何获取运行中JVM的Security类实时属性
好问题!我之前也碰到过类似的调试需求——要拿到java.security.Security维护的所有实时属性,但官方确实没有提供直接遍历所有属性的公开API。不过咱们可以通过反射来实现,因为这些属性本质上是存储在类内部的私有集合里的,下面是具体的方案:
核心实现思路
java.security.Security类把所有属性存在一个私有静态集合中(不同JDK版本可能用Map或Hashtable,比如OpenJDK 8+大多是volatile Map<String, String> props)。我们可以通过反射获取这个私有字段,然后遍历其中的键值对,就能拿到所有实时属性了——包括配置文件初始化的,以及通过Security.setProperty()动态修改/添加的。
代码示例
import java.security.Security; import java.lang.reflect.Field; import java.util.Map; public class SecurityPropsDebugger { public static void main(String[] args) throws Exception { // 定位Security类中的私有静态字段"props" Field propsField = Security.class.getDeclaredField("props"); // 开启字段的访问权限(因为是私有字段) propsField.setAccessible(true); // 取出字段值,转换为Map类型 Map<String, String> securityProps = (Map<String, String>) propsField.get(null); // 遍历并打印所有属性 System.out.println("当前JVM中Security类的实时属性列表:"); for (Map.Entry<String, String> entry : securityProps.entrySet()) { System.out.printf("属性名:%s,值:%s%n", entry.getKey(), entry.getValue()); } } }
注意事项
- JDK版本兼容性:不同厂商(Oracle JDK/OpenJDK)或不同版本的JDK,这个私有字段的名称或类型可能有变化。比如有些早期版本用的是
Hashtable而非Map,如果遇到类型转换错误,可以尝试把Map换成Hashtable再试。 - 模块系统限制(Java 9+):如果你的项目用了Java模块系统,直接运行上面的代码可能会抛出
IllegalAccessException。这时候需要在JVM启动参数中添加:
或者在--add-opens java.base/java.security=ALL-UNNAMEDmodule-info.java中声明对java.security模块的访问权限。 - 反射的风险:反射会破坏Java的封装性,而且如果未来JDK内部实现变更,这段代码可能会失效。所以只建议在调试场景下使用,不要放到生产代码里。
- 替代方案(无反射):如果不想用反射,你可以收集所有已知的安全属性名称(比如从
java.security配置文件、官方文档里找),然后逐个调用Security.getProperty()获取值。但这种方法无法覆盖动态添加的新属性,只能拿到已知的属性。
内容的提问来源于stack exchange,提问作者jr10
相关产品推荐
相关产品推荐

