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

获取当前Jvm的内存信息

/*
* 获取当前jvm的内存信息,返回的值是 字节为单位
* */
public static void getFreeMemory() {
//获取可用内存
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 void getAvailableProcessors() {
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中拷贝文件防止阻塞的写法

打开记事本

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");

得到系统的环境变量

@Test
public void dirRuntimeProcess() throws IOException, InterruptedException {
Process process = Runtime.getRuntime().exec("cmd.exe /c echo %JAVA_HOME%");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(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的版本号,这个和上述的不一样

@Test
public void getJavaVersion() {
try {
Process process = Runtime.getRuntime().exec("javac -version");
BufferedReader br = new BufferedReader(new InputStreamReader(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();
}
}

执行外部命令得到的结果

@Test
public void execProgramC() {
try {
Process process = Runtime.getRuntime().exec("C:/Users/76801/Desktop/huhx.exe");
BufferedReader br = new BufferedReader(new InputStreamReader(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<stdio.h>

void main() {
printf("Hello World.");
}

导出mysql脚本

@Test
public void execMysqldump() throws IOException, 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 extends Thread {

    InputStream is;
String type; public StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
} public void run() {
try (InputStreamReader isr = new InputStreamReader(is);) {
BufferedReader br = new BufferedReader(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 class TestShutdownHook {
    public static void main(String[] args) {
      // thread1
        Thread thread1 = new Thread() {
         public void run() {
            System.out.println("thread1");
         }
        };       // thread2
      Thread thread2 = new Thread() {
         public void run() {
            System.out.println("thread2");
            }
        };       // shutdownThread
        Thread shutdownThread = new Thread() {
         public void run() {
            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(int status) {
Runtime.getRuntime().exit(status);
}

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

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

Java中RunTime类介绍的更多相关文章

  1. java中Runtime类和Process类的简单介绍

    在java.lang包当中定义了一个Runtime类,在java中对于Runtime类的定义如下: Java code public class Runtime extends Object 每个 J ...

  2. java中Runtime类详细介绍

    Runtime类描述了虚拟机一些信息.该类采用了单例设计模式,可以通过静态方法 getRuntime()获取Runtime类实例.下面演示了获取虚拟机的内存信息: package Main; publ ...

  3. java中Runtime类

    一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象, ...

  4. Java中BigDecimal类介绍及用法

    Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecimal 类,用于高精度计算. 其中 BigInteger 类是 ...

  5. 浅析Java.lang.Runtime类

    一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象, ...

  6. 深入研究java.lang.Runtime类【转】

    转自:http://blog.csdn.net/lastsweetop/article/details/3961911 目录(?)[-] javalang 类 Runtime getRuntime e ...

  7. 【转】深入研究java.lang.Runtime类

    一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象, ...

  8. 【JAVA零基础入门系列】Day11 Java中的类和对象

    今天要说的是Java中两个非常重要的概念--类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外观特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征 ...

  9. Java中Optional类的使用

    从 Java 8 引入的一个很有趣的特性是 Optional  类.Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都 ...

随机推荐

  1. 我的sourceinsight的配置

    下面是我的sourceinsight的配置,点击下面的链接,下载*.em文件,将他们添加到Base工程,设置相应的快捷键即可,或者导入下载的配置文件. http://pan.baidu.com/s/1 ...

  2. win10怎么彻底关闭自动更新

    原文:https://jingyan.baidu.com/article/9faa7231e7b78b473c28cbb6.html 方法/步骤   1 单击左下角开始菜单点击设置图标进入设置界面 2 ...

  3. 如何使用V7包中ActionBar(Eclipse版)

    转自:http://blog.csdn.net/appte/article/details/11712591 以前3.0以前的版本要使用ActionBar,必须使用国外大牛写的ActionBarShe ...

  4. 排查Hive报错:org.apache.hadoop.hive.serde2.SerDeException: java.io.IOException: Start of Array expected

    CREATE TABLE json_nested_test ( count string, usage string, pkg map<string,string>, languages ...

  5. 一个 forceLayout() 和 requestLayout() 的测试

    两个view: 一个是系统默认的FrameLayout,  A 一个是自己自定义的MyView extends View,重载了onMeasure函数(): B @Override protected ...

  6. 浏览器User-Agent的详细信息

    PC端: safari 5.1 – MACUser-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit ...

  7. Spark源码分析:多种部署方式之间的区别与联系(转)

    原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...

  8. Android两次后退键退出

    转载请注明出处:http://blog.csdn.net/javacattle/article/details/41964045 仅仅要在 *.Java 文件里加入就可以 private int ba ...

  9. 转:如何转换Android打包用jks格式keystore证书为Air用pkcs12格式p12证书

    转自:http://blog.k-res.net/archives/1539.html 如何转换Android打包用jks格式keystore证书为Air用pkcs12格式p12证书 六月 11, 2 ...

  10. 近200篇机器学习&深度学习资料分享(含各种文档,视频,源码等)(1)

    原文:http://developer.51cto.com/art/201501/464174.htm 编者按:本文收集了百来篇关于机器学习和深度学习的资料,含各种文档,视频,源码等.而且原文也会不定 ...