java 岛_Java中RunTime类介绍

本文详细介绍了Java中的Runtime类,包括如何获取Runtime实例、获取JVM内存信息、处理器核心数,以及如何执行系统命令。Runtime.exec()方法用于执行系统命令,其不同重载方法提供了不同的参数选项。在使用时需要注意子进程的管理和资源释放,避免阻塞和内存浪费。此外,还提到了Runtime.addShutdownHook()方法,用于在JVM关闭时执行清理任务。
摘要由CSDN通过智能技术生成

Runtime 类代表着Java程序的运行时环境,每个Java程序都有一个Runtime实例,该类会被自动创建,我们可以通过Runtime.getRuntime() 方法来获取当前程序的Runtime实例。

获取当前Jvm的内存信息

/** 获取当前jvm的内存信息,返回的值是 字节为单位

**/

public static voidgetFreeMemory() {//获取可用内存

long value =Runtime.getRuntime().freeMemory();

System.out.println("可用内存为:"+value/1024/1024+"mb");//获取jvm的总数量,该值会不断的变化

long totalMemory =Runtime.getRuntime().totalMemory();

System.out.println("全部内存为:"+totalMemory/1024/1024+"mb");//获取jvm 可以最大使用的内存数量,如果没有被限制 返回 Long.MAX_VALUE;

long maxMemory =Runtime.getRuntime().maxMemory();

System.out.println("可用最大内存为:"+maxMemory/1024/1024+"mb");

}

获取jvm可用的处理器核心的数量

一般可以和newFixedThreadPool一起使用

/** 获取jvm可用的处理器核心的数量

**/

public static voidgetAvailableProcessors() {int value =Runtime.getRuntime().availableProcessors();

System.out.println(value);

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

}

执行系统命令

RunTime.getRuntime().exec()的构造方法

public Process exec(String command)-----在单独的进程中执行指定的字符串命令。public Process exec(String [] cmdArray)---在单独的进程中执行指定命令和变量public Process exec(String command, String [] envp)----在指定环境的独立进程中执行指定命令和变量public Process exec(String [] cmdArray, String [] envp)----在指定环境的独立进程中执行指定的命令和变量public Process exec(String command,String[] envp,File dir)----在有指定环境和工作目录的独立进程中执行指定的字符串命令public Process exec(String[] cmdarray,String[] envp,File dir)----在指定环境和工作目录的独立进程中执行指定的命令和变量

Process的几种方法

1.destroy():杀掉子进程

2.exitValue():返回子进程的出口值,值 0 表示正常终止

3.getErrorStream():获取子进程的错误流

4.getInputStream():获取子进程的输入流

5.getOutputStream():获取子进程的输出流

6.waitFor():导致当前线程等待,如有必要,一直要等到由该Process对象表示的进程已经终止。如果已终止该子进程,此方法立即返回。如果没有终止该子进程,调用的线程将被阻塞,直到退出子进程,根据惯例,0 表示正常终止

注意:在java中,调用runtime线程执行脚本是非常消耗资源的,所以切忌不要频繁使用!

在调用runtime去执行脚本的时候,其实就是JVM开了一个子线程去调用JVM所在系统的命令,其中开了三个通道:输入流、输出流、错误流,其中输出流就是子线程走调用的通道。

大家都知道,waitFor是等待子线程执行命令结束后才执行, 但是在runtime中,打开程序的命令如果不关闭,就不算子线程结束。比如以下代码。

private static Process p = null;

p= Runtime.getRuntime().exec("notepad.exe");

p.waitFor();

System.out.println("-------------------我被执行了-------------------");

以上代码中,打开windows中记事本。如果我们不手动关闭记事本,那么输出语句就不会被执行,这点是需要理解的。

process的阻塞

在runtime执行大点的命令中,输入流和错误流会不断有流进入存储在JVM的缓冲区中,如果缓冲区的流不被读取被填满时,就会造成runtime的阻塞。所以在进行比如:大文件复制等的操作时,我们还需要不断的去读取JVM中的缓冲区的流,来防止Runtime的死锁阻塞。

代码:linux中拷贝文件防止阻塞的写法

6c1555302777729326ca3efa0910d9ec.png

6c1555302777729326ca3efa0910d9ec.png

打开记事本

Runtime.getRuntime().exec("notepad.exe");

打开某个文件(不管是word还excel等等文件)

Runtime.getRuntime().exec("cmd /c start " + "\"\" \"" + path + "\"");

打开ie浏览器

Runtime.getRuntime().exec("C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE");

得到系统的环境变量

@Testpublic void dirRuntimeProcess() throwsIOException, InterruptedException {

Process process= Runtime.getRuntime().exec("cmd.exe /c echo %JAVA_HOME%");

BufferedReader bufferedReader= new BufferedReader(newInputStreamReader(process.getInputStream()));

String string= null;while ((string = bufferedReader.readLine()) != null) {

System.out.println(string);//D:\Java\jdk\jdk1.8.0_152

}

process.waitFor();

System.out.println("return: " + process.exitValue()); //return: 0

}

得到java的版本号,这个和上述的不一样

@Testpublic voidgetJavaVersion() {try{

Process process= Runtime.getRuntime().exec("javac -version");

BufferedReader br= new BufferedReader(newInputStreamReader(process.getErrorStream()));

String line= null;while ((line = br.readLine()) != null)

System.out.println(line);//javac 1.8.0_152

process.waitFor();

System.out.println("Process exitValue: " +process.exitValue());

}catch(Throwable t) {

t.printStackTrace();

}

}

执行外部命令得到的结果

@Testpublic voidexecProgramC() {try{

Process process= Runtime.getRuntime().exec("C:/Users/76801/Desktop/huhx.exe");

BufferedReader br= new BufferedReader(newInputStreamReader(process.getInputStream()));

String line= null;while ((line = br.readLine()) != null)

System.out.println(line);//Hello World.

process.waitFor();

System.out.println("Process exitValue: " +process.exitValue());

}catch(Throwable t) {

t.printStackTrace();

}

}

huhx.c比较简单,就是打印一句话。

#include

voidmain() {

printf("Hello World.");

}

导出mysql脚本

@Testpublic void execMysqldump() throwsIOException, InterruptedException {

String execCommand= "cmd c/ D:/Java/mysqldump.exe -uhuhx -phuhx boot_learn > D:/bootlearn.sql";

System.out.println("exec command: " +execCommand);

Runtime runtime=Runtime.getRuntime();

Process p=runtime.exec(execCommand);

StreamGobbler errorGobbler= new StreamGobbler(p.getErrorStream(), "Error");

StreamGobbler outputGobbler= new StreamGobbler(p.getInputStream(), "Output");

errorGobbler.start();

outputGobbler.start();

p.waitFor();

System.out.println("successful." +p.exitValue());

}

上述也使用到了网上所说的读出窗口的标准输出缓冲区中的内容,仍旧没有解决Process的waitFor阻塞问题。下面是清空缓冲区的线程代码:

public class StreamGobbler extendsThread {

InputStream is;

String type;publicStreamGobbler(InputStream is, String type) {this.is =is;this.type =type;

}public voidrun() {try (InputStreamReader isr = newInputStreamReader(is);) {

BufferedReader br= newBufferedReader(isr);

String line= null;while ((line = br.readLine()) != null) {if (type.equals("Error")) {

System.out.println("Error :" +line);

}else{

System.out.println("Debug:" +line);

}

}

}catch(IOException e) {

e.printStackTrace();

}

}

}

代码的目标是导出mysql数据库的脚本。没有找到问题的解决方案,运行环境是win10,jdk1.8。

在JVM中增加一个关闭的钩子

阅读ElasticSearch的源码时,BootStrap类中调用了Runtime.getRuntime().addShutdownHook方法。接下来对java.lang包中的Runtime类的addShutdownHook方法进行说明。

这个方法的意思就是在JVM中增加一个关闭的钩子,当JVM关闭的时候,会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子,当系统执行完这些钩子后,JVM才会关闭。所以这些钩子可以在JVM关闭的时候进行内存清理、对象销毁等操作。

为了更清晰的说明,编写如下程序:

public classTestShutdownHook {public static voidmain(String[] args) {//thread1

Thread thread1 = newThread() {public voidrun() {

System.out.println("thread1");

}

};//thread2

Thread thread2 = newThread() {public voidrun() {

System.out.println("thread2");

}

};//shutdownThread

Thread shutdownThread = newThread() {public voidrun() {

System.out.println("shutdownThread");

}

};

Runtime.getRuntime().addShutdownHook(shutdownThread);

thread1.start();

thread2.start();

}

}

输出结果:

thread1

thread2

shutdownThread

thread2

thread1

shutdownThread

无论是先打印thread1还是thread2,shutdownThread 线程都是最后执行的(因为这个线程是在JVM执行关闭前才会执行)。

关闭JVM程序

Runtime的exit表示的关闭JVM程序,但是不释放内存,举例:

System.exit(0);//表示正常程序的关闭,执行的是以下操作:

public static void exit(intstatus) {

Runtime.getRuntime().exit(status);

}

备注:如果是 0表示正常关闭,如果是非0表示异常关闭,如果想释放内存的话,用“dispose()”关闭当前程序,并释放资源。

System.exit()的内部实现也是Runtime.getRuntime().exit();

来源:oschina

链接:https://my.oschina.net/u/4415205/blog/3788304

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值