Java ProcessHandle无法正常获取命令行参数问题求助
问题:MacOS下Java无法获取含$符号的命令行参数?
环境信息
- 系统:MacOS
- JVM版本:
java version "17.0.2" 2022-01-18 LTS Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86) Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
复现步骤
- 编写如下Java代码:
public class Main { public static void main(String[] args) { System.out.println(ProcessHandle.current().info().commandLine().orElse("none")); } }
- 执行命令:
java "Main" "--username" "Steve47876" "--version" "1.20.1-fabric" "--gameDir" "/Users/zhaoliyan/Library/Application Support/minecraft/versions/1.20.1-fabric" "--assetsDir" "/Users/zhaoliyan/Library/Application Support/minecraft/assets" "--assetIndex" "5" "--uuid" "b7374a0acf0743e79a7a0e2cad64c9f9" "--accessToken" "eyJraWQiOiJhYzg07f3G03Vr3bhNG6vdsG7DD8QehRpITidVEZuo" "--clientId" "${clientid}" "--xuid" "${auth_xuid}" "--userType" "msa" "--versionType" "HMCL 3.5.5" "--width" "854" "--height" "480"
问题现象
程序执行后输出none,无法获取完整命令行。
更新发现
当命令行参数中包含$符号(如$a、${a})时,Java就无法获取到命令行,疑问:这是否属于Java的Bug?
解答
这不是Java的Bug,问题根源在Shell的变量解析行为上:
在MacOS默认的bash/zsh环境中,${clientid}这类带$的语法会被Shell识别为变量引用。如果这些变量未定义,Shell会直接将其替换为空字符串;更关键的是,Shell处理后的命令行才会传递给JVM,而ProcessHandle.current().info().commandLine()获取的是Shell传递给JVM的最终参数,并非你输入的原始命令行。另外MacOS不像Linux依赖/proc文件系统暴露进程原始命令行,JVM只能拿到Shell处理后的结果,所以会出现获取失败的情况。
解决办法
要让Java拿到包含$的原始参数,需要阻止Shell解析$符号,有两种常用方式:
- 对
$进行转义,在前面加反斜杠:
java "Main" "--username" "Steve47876" "--version" "1.20.1-fabric" "--gameDir" "/Users/zhaoliyan/Library/Application Support/minecraft/versions/1.20.1-fabric" "--assetsDir" "/Users/zhaoliyan/Library/Application Support/minecraft/assets" "--assetIndex" "5" "--uuid" "b7374a0acf0743e79a7a0e2cad64c9f9" "--accessToken" "eyJraWQiOiJhYzg07f3G03Vr3bhNG6vdsG7DD8QehRpITidVEZuo" "--clientId" "\${clientid}" "--xuid" "\${auth_xuid}" "--userType" "msa" "--versionType" "HMCL 3.5.5" "--width" "854" "--height" "480"
- 用单引号包裹含
$的参数,单引号内的内容不会被Shell解析:
java "Main" "--username" "Steve47876" "--version" "1.20.1-fabric" "--gameDir" "/Users/zhaoliyan/Library/Application Support/minecraft/versions/1.20.1-fabric" "--assetsDir" "/Users/zhaoliyan/Library/Application Support/minecraft/assets" "--assetIndex" "5" "--uuid" "b7374a0acf0743e79a7a0e2cad64c9f9" "--accessToken" "eyJraWQiOiJhYzg07f3G03Vr3bhNG6vdsG7DD8QehRpITidVEZuo" "--clientId" '${clientid}' "--xuid" '${auth_xuid}' "--userType" "msa" "--versionType" "HMCL 3.5.5" "--width" "854" "--height" "480"
处理后,参数会原封不动传递给Java,ProcessHandle.current().info().commandLine()就能正常获取完整命令行了。
内容的提问来源于stack exchange,提问作者zly2006
相关产品推荐
相关产品推荐

