JAVA 【精】从底层分析RunTime出错,Cmd命令执行正常

编程入门 行业动态 更新时间:2024-10-21 06:46:01

JAVA 【精】从<a href=https://www.elefans.com/category/jswz/34/1768082.html style=底层分析RunTime出错,Cmd命令执行正常"/>

JAVA 【精】从底层分析RunTime出错,Cmd命令执行正常

奥特曼超人杜锦阳曾经说过:“宁可在法度外灭亡,不在法度中生存。”



Cmd命令执行失败,可能大家开发中经常会有遇到如下问题,可是百度谷歌却出不来,博主踩的坑共享给大家:

  • 报错 CreateProcess error=2, ϵͳÕҲ»µ½ָ¶
  • JAVA cmd执行失败 JAVA
  • RunTime报错,cmd下却执行正常
  • ProcessBuilder异常CreateProcess error=2, ϵͳÕҲ»µ½ָ¶
  • JAVA CMD.EXE /C 的问题


     这里使用的是数组命令,这里记录下这些问题,最近遇到一个比较变态问题,这里是要做个 在线安卓多渠道打包 的东西,中间涉及解包,回编等等……
     主要遇到的问题是传入的参数,怎么空格都不行,折腾了一上午,后来看了底层代码才搞定,先来总结下解决的过程和方法。

    1. 假设你要执行 cmd.exe /C 的命令,这里记住,如果执行的是外部 .exe .bat 之类的,一定不要在数组面前加 CMD /C,如果加了,那就是 执行命令失败 !

    2. 假设你要执行多个参数的,记住,不要学网上的博客在数组命令前加“”,这个会挂逼。

    3. 假设你要执行多个参数的,不用和PC上Cmd一样去空格,之前我也是尝试了,发现不行去看的底层源码才发现,底层会读取空格并换成“”,底下会把源码贴出来。

    4. 最后一点,只要当成参数传入替换即可,不要主动去空格!


一、 CreateProcess error=2, ϵͳÕҲ»µ½ָ¶

 这个报错有2种常见方式,常见的是直接用 CMD.EXE\C 之后调用了外部的exe

//执行代码
Runtime.getRuntime().exec(cmds);
  • 第一种: 这里传入的错误参数:”D:/dujinyang/immqy.exe
    d”,”k”,”D:/dujinyang/immqy_new”,为什么会出现这种,因为指令之间如果有空格而不用不同的字符串隔开,就会无法识别指令。

  • 第二种: 这里传入的参数都没有问题,只是位符错误,所以才报了这种错,这个时候就要换成其它命令来尝试这种错误,而且,CMD/C
    接收的是默认的参数,如果带exe,会被识别成一个程序,如果带参数,除非是bat能直接接收,否则只会当成一个程序处理,这里如果用apktool也会出现这种情况。


二、cmd执行失败

  • 第一种:参数错误,不用多说,解决办法,在string[]组里替换掉自己的参数来测试,如果测试OK再还原占位符。
  • 第二种:占位符错误,解决办法,还是替换参数来测试。

    例子:

//正确代码
String[] CMD_APKTOOL_D = new String [] { "CMD.EXE", "/C","%1","d","-f","%2","-o","%3"};//解压/**以下都是错误代码方式**/String[] CMD_APKTOOL_D = new String [] { "CMD.EXE", "/C"," %1"," d"," -f"," %2"," -o","%3"};//解压String[] CMD_APKTOOL_D = new String [] { "CMD.EXE", "/C","%1"," d "," -f ","%2"," -o","%3"};//解压String[] CMD_APKTOOL_D = new String [] { "CMD.EXE", "/C","%1","","d","","-f","","%2","","-o","","%3"};//解压


三、源码分析

 为什么会出现这么多的错误,而且空格符又有这么多问题,查了ProcessBuilder相关的API,JAVA RUNTIME什么都看了,没发现什么问题,后来调试中在ProcessImpl.class发现了一段代码,看下图

/** @(#)ProcessImpl.java 1.32 06/03/22** Copyright 2006 Sun Microsystems, Inc. All rights reserved.* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*/package java.lang;import java.io.*;/* This class is for the exclusive use of ProcessBuilder.start() to* create new processes.** @author Martin Buchholz* @version 1.32, 06/03/22* @since   1.5*/final class ProcessImpl extends Process {// System-dependent portion of ProcessBuilder.start()static Process start(String cmdarray[],java.util.Map<String,String> environment,String dir,boolean redirectErrorStream)throws IOException{String envblock = ProcessEnvironment.toEnvironmentBlock(environment);return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream);}private long handle = 0;private FileDescriptor stdin_fd;private FileDescriptor stdout_fd;private FileDescriptor stderr_fd;private OutputStream stdin_stream;private InputStream stdout_stream;private InputStream stderr_stream;private ProcessImpl(String cmd[],String envblock,String path,boolean redirectErrorStream)throws IOException{// Win32 CreateProcess requires cmd[0] to be normalizedcmd[0] = new File(cmd[0]).getPath();StringBuilder cmdbuf = new StringBuilder(80);for (int i = 0; i < cmd.length; i++) {if (i > 0) {cmdbuf.append(' ');}String s = cmd[i];if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {if (s.charAt(0) != '"') {cmdbuf.append('"');cmdbuf.append(s);if (s.endsWith("\\")) {cmdbuf.append("\\");}cmdbuf.append('"');} else if (s.endsWith("\"")) {/* The argument has already been quoted. */cmdbuf.append(s);} else {/* Unmatched quote for the argument. */throw new IllegalArgumentException();}} else {cmdbuf.append(s);}}String cmdstr = cmdbuf.toString();stdin_fd  = new FileDescriptor();stdout_fd = new FileDescriptor();stderr_fd = new FileDescriptor();handle = create(cmdstr, envblock, path, redirectErrorStream,stdin_fd, stdout_fd, stderr_fd);java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {public Object run() {stdin_stream =new BufferedOutputStream(new FileOutputStream(stdin_fd));stdout_stream =new BufferedInputStream(new FileInputStream(stdout_fd));stderr_stream =new FileInputStream(stderr_fd);return null;}});}public OutputStream getOutputStream() {return stdin_stream;}public InputStream getInputStream() {return stdout_stream;}public InputStream getErrorStream() {return stderr_stream;}public void finalize() {close();}public native int exitValue();public native int waitFor();public native void destroy();private native long create(String cmdstr,String envblock,String dir,boolean redirectErrorStream,FileDescriptor in_fd,FileDescriptor out_fd,FileDescriptor err_fd)throws IOException;private native void close();
}



那么提炼这段代码再打印出来,我们可以发现很大的问题是在 s.indexOf(' ') >= 0 这里,那么我们改下这段代码就能实现输出,代码如下

/*** 模拟底层CMD实现输出查看命令行* @see ProcessImple.class* @author KARL-dujinyang* @param cmd* @return*/public static String processImpl(String [] cmd){System.out.println("dujinyang start");StringBuilder cmdbuf = new StringBuilder(80);for (int i = 0; i < cmd.length; i++) {if (i > 0) {cmdbuf.append(' ');}String s = cmd[i];if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {if (s.charAt(0) != '"') {cmdbuf.append('"');cmdbuf.append(s);if (s.endsWith("\\")) {cmdbuf.append("\\");}cmdbuf.append('"');} else if (s.endsWith("\"")) {/* The argument has already been quoted. */cmdbuf.append(s);} else {/* Unmatched quote for the argument. */throw new IllegalArgumentException();}} else {cmdbuf.append(s);}}System.out.println(cmdbuf.toString());System.out.println("dujinyang end");}



最后执行正确的String[] 数组,发现没什么问题,搞定!测试加上 "CMD.EXE", "/C" 的话,就会执行失败。



执行命令的代码我也共享下吧 ~.~


|| 版权声明:本文为博主杜锦阳原创文章,转载请注明出处。

如果有其它问题可留言或加入安卓移动技术精英群(246231638)

更多推荐

JAVA 【精】从底层分析RunTime出错,Cmd命令执行正常

本文发布于:2024-02-27 05:05:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1705282.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:底层   命令   JAVA   Cmd   RunTime

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!