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. Raw-OS源代码分析之同优先级任务切换

    分析的内核版本号截止到2014-04-15,基于1.05正式版,blogs会及时跟进最新版本号的内核开发进度,若源代码凝视出现"???"字样,则是未深究理解部分. Raw-OS官方 ...

  2. UVa 1329 - Corporative Network Union Find题解

    UVa的题目好多,本题是数据结构的运用,就是Union Find并查集的运用.主要使用路径压缩.甚至不须要合并树了,由于没有反复的连线和改动单亲节点的操作. 郁闷的就是不太熟悉这个Oj系统,竟然使用库 ...

  3. 命令方式启动安卓模拟器(M9)

    H:\Android\M9SDK_windows_1.0\platforms\android-2.3.1>emulator.exe -sysdir H:\Android\M9SDK_window ...

  4. iOS开源项目:FlatUIKit

    FlatUIKit是iOS中具有扁平化风格的UI(Flat UI)组件.FlatUIKit的设计灵感来源于Flat UI和Kyle Miller.FlatUIKit中的组件是通过扩展(category ...

  5. DEDECMS网站管理系统Get Shell漏洞

    漏洞版本: DEDECMS 5.3/5.6 漏洞描述: DedeCms 基于PHP+MySQL的技术开发,支持Windows.Linux.Unix等多种服务器平台,从2004年开始发布第一个版本开始, ...

  6. mysql的安全性机制

    MySQL中主要包括两种用户:root用户和普通用户,其中前者为超级管理员,拥有MySQL提供的一切权限:而普通用户则只能拥有创建用户时赋予它的权限. MySQL的安全性机制主要包括权限机制,用户机制 ...

  7. DNS named.conf文件详解

    配置文件: /etc/named.conf /在NAMED.CONF         配置文件中使用//和/* */来进行注释, options { /*OPTIONS选项用来定义一些影响整个DNS服 ...

  8. 十个书写Node.js REST API的最佳实践(上)

    收录待用,修改转载已取得腾讯云授权 原文:10 Best Practices for Writing Node.js REST APIs 我们会通过本文介绍下书写Node.js REST API的最佳 ...

  9. [Compose] 9. Delay Evaluation with LazyBox

    We rewrite the Box example using lazy evaulation. Here is Box example: const Box = (x) => ({ map: ...

  10. aes加密在linux下会生成随机key的解决办法

    直接贴代码了: package com.segerp.tygl.weixin.common; import java.io.UnsupportedEncodingException; import j ...