浅析Java.lang.Process类 --- java中运行cmd命令

一、概述

Process类是一个java.lang包下的一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序)。

Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获取相关信息。

首先来看以下Process类的源码:

public abstract class Process {

public abstract OutputStream getOutputStream();

public abstract InputStream getInputStream();

public abstract InputStream getErrorStream();

public abstract int waitFor() throws InterruptedException;

public boolean waitFor(long timeout, TimeUnit unit)
       throws InterruptedException
   {
       long startTime = System.nanoTime();
       long rem = unit.toNanos(timeout);

       do {
           try {
               exitValue();
               return true;
           } catch(IllegalThreadStateException ex) {
               if (rem > 0)
                   Thread.sleep(
                       Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
           }
           rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
       } while (rem > 0);
       return false;
   }
   public abstract int exitValue();
   
   public abstract void destroy();
   
   public Process destroyForcibly() {
       destroy();
       return this;
   }
   
   public boolean isAlive() {
       try {
           exitValue();
           return false;
       } catch(IllegalThreadStateException e) {
           return true;
       }
   }
}    

从官方文档看下这些方法都是做什么的:

abstract void	destroy()
杀死子进程。
Process	destroyForcibly()
杀死子进程。
abstract int	exitValue()
返回子进程的退出值。
abstract InputStream	getErrorStream()
返回连接到子进程的错误输出的输入流。
abstract InputStream	getInputStream()
返回连接到子进程的正常输出的输入流。
abstract OutputStream	getOutputStream()
返回连接到子进程正常输入的输出流。
boolean	isAlive()
测试这个Process代表的子Process是否存活。
abstract int waitFor()
导致当前线程等待,如有必要,直到由此Process对象表示的进程已终止。
boolean	waitFor(long timeout, TimeUnit unit)
使当前线程等待,如有必要,直到此Process对象表示的子 Process已终止,或指定的等待时间过去。

二:如何创建process进程
1、每个 ProcessBuilder 实例管理一个进程属性集。start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。
(processBuilder这个是JDK5中新添加的final类)
2、Runtime.exec() 方法创建一个本机进程,并返回 Process 子类的一个实例。

三:代码示例:

/**
 * @Author: chuxia0811
 * @Date: 2021/2/21 10:24
 * @Description :
 */
public class ProcessDemo {
    public static void main(String[] args) {
        try {
            Runtime rt = Runtime.getRuntime();

            Process pr = rt.exec("cmd /c del test111.txt",null,new File("E:"));

            BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream(), "GBK"));

            String line = null;

            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }

            int exitVal = pr.waitFor();
            System.out.println("Exited with error code " + exitVal);

        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

在E:盘目录下提前建一个test111.txt的文件,执行以上操作即可由java代码通过process类和cmd命令实现指定目录的文件的删除。

这里要注意一个坑:外部程序在执行结束后将会自动关闭,否则不管是字符流还是字节流均由于既读不到数据,又读不到流结束符而出现阻塞Java进程运行的情况。

而 cmd /c 就是告诉cmd环境进程,当执行完成后关闭自身。

这里要特别注意:Runtime.exec()这个方法,我们来看下源码:

public Process exec(String command, String[] envp, File dir)
        throws IOException {
        if (command.length() == 0)
            throw new IllegalArgumentException("Empty command");

        StringTokenizer st = new StringTokenizer(command);
        String[] cmdarray = new String[st.countTokens()];
        for (int i = 0; st.hasMoreTokens(); i++)
            cmdarray[i] = st.nextToken();
        return exec(cmdarray, envp, dir);
    }
public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }

第一个参数command为要执行的命令,第二个参数envp为可以传递的String类型数组参数,第三个dir表示要切换或者要操作的目录,正如上面的demo代码:

Process pr = rt.exec("cmd /c del test111.txt",null,new File("E:"));

表示先将目录切换到E盘,然后执行del test111.txt 删除文件操作,操作完成后cmd /c 关闭退出进程。

回答: java.lang.ClassNotFoundException是一个常见的错误,通常有几个可能的原因。首先,可能是项目没有引入该所属的jar包的坐标。你可以查看项目的pom文件,确认是否引入了该jar包的坐标,或者检查项目的Maven dependencies下是否有该class的jar包。\[1\]其次,可能是项目多个maven坐标引入的jar包所依赖有所重叠,导致版本不一致产生冲突。你可以检查刚刚加入的maven坐标所依赖的jar包,与项目其他maven坐标引入的jar包所依赖的jar包是否相同。\[1\]简单的解决办法是,将刚刚引入的jar包注释掉,然后复制Maven dependencies下所有的jar包名称到记事本文件,再将刚刚引入的jar包解注释,再次复制所有的jar包名称到记事本文件,最后使用代码比对工具比对两者所引入的jar包的区别,以查看是否有jar包依赖的冲突。\[1\]另外,有时候该错误可能是因为在部署路径下的lib文件夹缺少相应的jar包。你可以进入到tomcat的部署路径下的lib文件夹,检查是否缺少相应的jar包。\[2\]最后,需要注意的是,该错误通常是在程序运行时找不到,而不是在编译时找不到。因此,即使在IDEA编译时没有报错,但在运行时仍然可能找不到对应的。\[3\]希望这些解释能帮助你解决java.lang.ClassNotFoundException的问题。 #### 引用[.reference_title] - *1* [maven工程下 java.lang.ClassNotFoundException原因浅析](https://blog.csdn.net/farYang/article/details/53168233)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Maven项目下java.lang.ClassNotFoundException的解决方法](https://blog.csdn.net/zym2895756/article/details/78233688)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [maven依赖传统导致的 java.lang.NoClassDefFoundError和ClassNotFoundException产生原因以及解决方法](https://blog.csdn.net/qq_45171957/article/details/126899231)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初夏0811

你的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值