Java中RunTime类介绍

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

原文地址:https://www.cnblogs.com/shamo89/p/9807019.html

时间: 2024-10-11 13:19:51

Java中RunTime类介绍的相关文章

JAVA中Runtime类以及exec()方法,Process的使用

package ioTest.io1; /* * Runtime:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接. * 这也是jvm实现跨平台的一个重要原因. * 可以通过 getRuntime 方法获取当前运行时. * API分析: * public class Runtime extends Object * 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接. * 可以通过 getRuntime 方法获

JAVA中的饿汉式和饱汉式单例模式及jdk中Runtime类的单例模式实现方式详解

一.描述 单例模式是一种非常常见的设计模式,即一个类只能有一个对象(实例),一般通过将该类的构造器私有化,来阻止在该类外创建该类的对象,并提供给外界一个唯一的对象(这个对象在该类中创建). java中的单例模式常见的有两种实现方式,一种是恶汉方式,即将该类对象用static休息并且在类加载的时候进行初始化:另一种是饱汉方式,在程序中需要用到该对象的时候才初始化,一旦初始化一次就不会再重新生成该对象. JDK中的Runtime类其实也是一种单例模式,而且其采用的是饿汉的方式. 二.源代码 pack

深入研究java.lang.Runtime类

深入研究java.lang.Runtime类 一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用.      一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为.

浅析Java.lang.Runtime类

一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用.      一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为.       当Applet和其他不被信任的代

深入研究java.lang.Runtime类(转)

一.概述      Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接.      一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用.      一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为.       当Applet和其他不被信任的代

转发 深入研究java.lang.Runtime类

转发 深入研究java.lang.Runtime类 前言:Java的类库日益庞大,所包含的类和接口也不计其数.但其中有一些非常重要的类和接口,是Java类库中的核心部分.常见的有String.Object.Class.Collection.ClassLoader.Runtime.Process...,熟悉这些类是学好Java的基础.而这些类一般不容易理解,需要做深入的研究和实践才能掌握.下面是我对这些类理解和使用的一些总结.欢迎你在阅读后将你宝贵的意见和读后感留下! 一.概述      Runt

探究Java中Map类

Map以按键/数值对的形式存储数据,和数组非常相似,在数组中存在的索引,它们本身也是对象.       Map的接口       Map---实现Map       Map.Entry--Map的内部类,描述Map中的按键/数值对.       SortedMap---扩展Map,使按键保持升序排列           关于怎么使用,一般是选择Map的子类,而不直接用Map类.       下面以HashMap为例.       public     static     void     ma

【转】java中Thread类方法介绍

原文: java中Thread类方法介绍 http://blog.csdn.net/seapeak007/article/details/53395609 这篇文章找时间分析一下!!!:http://blog.csdn.net/apei830/article/details/4503112 --------------------------------------------------------------- 方法摘要 static int activeCount()          

零基础入门学习java第十一节:Java中的类和对象

今天要说的是Java中两个非常重要的概念——类和对象. 什么是类,什么又是对象呢?类是对特定集合的概括描述,比如,人,这个类,外在特征上,有名字,有年龄,能说话,能吃饭等等,这是我们作为人类的相同特征,那么对象呢?我们口口声声说要面向对象编程,可是找了这么久也没找到对象,这还怎么编程(滑稽).此对象非彼对象,Java中的对象是某个具体类的实例,就好比你和我都是人类这个大类的一个实例个体,也就是说,我们都是人类的一个具体对象,我们有各自的名字和年龄. 那为什么要用类和对象这样的概念呢? 这是一个好