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

简介: 奥特曼超人杜锦阳曾经说过:“宁可在法度外灭亡,不在法度中生存。” Cmd命令执行失败,可能大家开发中经常会有遇到如下问题,可是百度谷歌却出不来,博主踩的坑共享给大家:报错 CreateProcess error=2, ϵͳÕҲ»µ½ָ¶ JAVA ...

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

深圳市米奇云科技有限公司



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 normalized
    cmd[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)

相关文章
|
11月前
|
安全 Java 编译器
new出来的对象,不一定在堆上?聊聊Java虚拟机的优化技术:逃逸分析
逃逸分析是一种静态程序分析技术,用于判断对象的可见性与生命周期。它帮助即时编译器优化内存使用、降低同步开销。根据对象是否逃逸出方法或线程,分析结果分为未逃逸、方法逃逸和线程逃逸三种。基于分析结果,编译器可进行同步锁消除、标量替换和栈上分配等优化,从而提升程序性能。尽管逃逸分析计算复杂度较高,但其在热点代码中的应用为Java虚拟机带来了显著的优化效果。
340 4
|
监控 Java Unix
6个Java 工具,轻松分析定位 JVM 问题 !
本文介绍了如何使用 JDK 自带工具查看和分析 JVM 的运行情况。通过编写一段测试代码(启动 10 个死循环线程,分配大量内存),结合常用工具如 `jps`、`jinfo`、`jstat`、`jstack`、`jvisualvm` 和 `jcmd` 等,详细展示了 JVM 参数配置、内存使用、线程状态及 GC 情况的监控方法。同时指出了一些常见问题,例如参数设置错误导致的内存异常,并通过实例说明了如何排查和解决。最后附上了官方文档链接,方便进一步学习。
3266 4
|
9月前
|
存储 Java Go
【Java】(3)8种基本数据类型的分析、数据类型转换规则、转义字符的列举
牢记类型转换规则在脑海中将编译和运行两个阶段分开,这是两个不同的阶段,不要弄混!
388 2
|
9月前
|
Java Go 开发工具
【Java】(9)抽象类、接口、内部的运用与作用分析,枚举类型的使用
抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接 口、枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类abstract static不能同时修饰一个方法。
359 1
|
10月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
数据采集 搜索推荐 算法
Java 大视界 -- Java 大数据在智能教育学习社区用户互动分析与社区活跃度提升中的应用(274)
本文系统阐述 Java 大数据技术在智能教育学习社区中的深度应用,涵盖数据采集架构、核心分析算法、活跃度提升策略及前沿技术探索,为教育数字化转型提供完整技术解决方案。
|
11月前
|
机器学习/深度学习 安全 Java
Java 大视界 -- Java 大数据在智能金融反洗钱监测与交易异常分析中的应用(224)
本文探讨 Java 大数据在智能金融反洗钱监测与交易异常分析中的应用,介绍其在数据处理、机器学习建模、实战案例及安全隐私等方面的技术方案与挑战,展现 Java 在金融风控中的强大能力。
|
12月前
|
存储 Java 大数据
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用(198)
简介:本文探讨Java大数据技术在智能家居能源消耗分析与节能策略中的应用。通过数据采集、存储与智能分析,构建能耗模型,挖掘用电模式,制定设备调度策略,实现节能目标。结合实际案例,展示Java大数据在智能家居节能中的关键作用。
|
Java 数据库连接 API
互联网大厂校招 JAVA 工程师笔试题解析及常见考点分析
本文深入解析互联网大厂校招Java工程师笔试题,涵盖基础知识(数据类型、流程控制)、面向对象编程(类与对象、继承与多态)、数据结构与算法(数组、链表、排序算法)、异常处理、集合框架、Java 8+新特性(Lambda表达式、Stream API)、多线程与并发、IO与NIO、数据库操作(JDBC、ORM框架MyBatis)及Spring框架基础(IoC、DI、AOP)。通过技术方案讲解与实例演示,助你掌握核心考点,提升解题能力。
515 2
|
Arthas 存储 监控
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)
1044 8