<p>System.getProperty 仅读取 JVM 启动时固化静态属性,无法获取硬件运行时数据、OS 环境变量、内核参数、动态系统状态;值不可靠、受安全策略限制、平台差异大,且 Android user 版本严格过滤 persist.* 等属性。</p>

System.getProperty 读取的是 JVM 启动时采集并固化的一组静态系统属性,不是实时操作系统状态,也不等同于环境变量或内核参数。它的能力边界很明确:只反映 JVM 自身视角下的运行环境快照,且受安全策略、启动配置和平台实现差异制约。
读取范围受限:仅限 JVM 启动时加载的属性
它无法获取以下几类信息:
- 硬件运行时数据(如 CPU 使用率、内存剩余量、磁盘 I/O)——这些需通过
java.lang.management的 MXBean 或 OSHI 等第三方库获取 - 操作系统环境变量(如 PATH、HOME)——必须用
System.getenv(),误用getProperty("PATH")会返回 null - 内核级参数(如 /proc/sys/net/ipv4/ip_forward)或 Android 的 persist.* 属性(在 user 版本中常被屏蔽)——这些属于底层 OS 或特定平台机制,JVM 不感知
- 动态变化的系统状态(如当前登录用户是否已切换、网络接口是否刚启用)——所有 getProperty 返回值在 JVM 生命周期内不变
值可靠性受限:格式不统一、版本不可控
像 os.name 这类关键属性,返回值依赖 JVM 实现和宿主系统,没有标准化输出:
- macOS 可能返回
"Mac OS X"、"Mac OS"或"darwin" - Windows Server 环境可能带
"Server"后缀,而普通桌面版不带 - 所有 Linux 发行版都返回
"Linux",无法区分 Ubuntu、CentOS 或 Alpine - 硬编码匹配(如
equals("Windows 10"))极易失效,应改用模糊判断(如toLowerCase().startsWith("windows"))
安全性与权限限制:非所有属性都可访问
在安全管理器启用或沙箱环境中,部分属性读取会被拦截:
- 调用
System.getProperty("user.dir")在 Applet 或某些容器中可能抛出SecurityException - 敏感属性(如自定义密钥路径)若通过
-D参数传入,本身就不该含密钥明文,否则易被其他进程通过 jstack 或 jinfo 泄露 - 无默认值的调用(
getProperty(key))返回 null,容易引发 NPE;建议统一使用带默认值的重载形式getProperty(key, "default")
平台与构建类型差异:Android user 版本更严格
在 Android 系统中,属性可见性受构建类型强约束:
- eng 和 userdebug 版本能读取
persist.bluetooth.disableabsvol等调试属性 - user 版本会主动过滤掉大量 persist.* 和 debug.* 属性,
getprop命令返回空,Java 层SystemProperties.get()同样拿不到 - 这种限制来自 system/core/init/property_service.cpp 中的白名单逻辑,与 JVM 无关,但直接影响上层 Java 调用结果
- 开发者不能绕过此限制,只能在 userdebug/eng 环境调试,或改用其他机制(如 SharedPreferences)传递必要配置

















