ZetCode

Java 运行时类

最后修改时间:2025 年 4 月 13 日

java.lang.Runtime 类提供了对 Java 运行时环境的访问。每个 Java 应用程序都有一个 Runtime 的单一实例,允许应用程序与其运行的环境进行交互。

Runtime 类不能直接实例化。应用程序必须使用静态 getRuntime 方法来获取当前运行时实例。此类提供了用于内存管理、执行进程和其他系统相关操作的方法。

Runtime 类方法

Runtime 类提供了几个重要的用于与 Java 运行时环境交互的方法。这些方法包括内存管理、进程执行和系统信息的方法。该类还提供了用于关闭操作的钩子。

public class Runtime {
    public static Runtime getRuntime() {...}
    public void exit(int status) {...}
    public void addShutdownHook(Thread hook) {...}
    public boolean removeShutdownHook(Thread hook) {...}
    public long freeMemory() {...}
    public long totalMemory() {...}
    public long maxMemory() {...}
    public void gc() {...}
    public Process exec(String command) {...}
    public int availableProcessors() {...}
}

上面的代码显示了 Runtime 类提供的主要方法。这些方法允许 Java 应用程序以各种方式与其运行时环境进行交互,从执行系统命令到管理内存。

获取 Runtime 实例

getRuntime 方法返回与当前 Java 应用程序关联的运行时对象。这是获取 Runtime 实例的唯一方法,因为构造函数是私有的。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        System.out.println("Runtime instance obtained: " + runtime);
        System.out.println("Available processors: " + 
                         runtime.availableProcessors());
        System.out.println("Free memory: " + runtime.freeMemory() + " bytes");
        System.out.println("Total memory: " + 
                         runtime.totalMemory() + " bytes");
        System.out.println("Max memory: " + runtime.maxMemory() + " bytes");
    }
}

此示例演示了如何获取 Runtime 实例并使用它来获取基本的系统信息。availableProcessors 方法返回 JVM 可用的处理器数量,而内存方法提供有关当前内存状态的信息。

执行外部进程

exec 方法在一个单独的进程中执行指定的字符串命令。这允许 Java 应用程序通过运行系统命令或其他可执行文件与底层操作系统进行交互。

Main.java
package com.zetcode;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("ls -l");
            
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream()));
            
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            
            int exitCode = process.waitFor();
            System.out.println("\nExited with code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

此示例显示了如何执行系统命令(Unix 系统上的 ls -l)并读取其输出。Process 对象提供对子进程的输入、输出和错误流的访问。waitFor 方法等待进程完成。

内存管理

Runtime 类提供了几种用于监视和管理内存使用情况的方法。这些方法包括 freeMemorytotalMemorymaxMemory,它们报告 JVM 的当前内存状态。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        System.out.println("Initial memory stats:");
        printMemoryStats(runtime);
        
        // Allocate some memory
        byte[] bytes = new byte[2 * 1024 * 1024]; // 2MB
        
        System.out.println("\nAfter allocation:");
        printMemoryStats(runtime);
        
        // Suggest garbage collection
        runtime.gc();
        
        System.out.println("\nAfter GC:");
        printMemoryStats(runtime);
    }
    
    private static void printMemoryStats(Runtime runtime) {
        System.out.println("Free memory: " + runtime.freeMemory() / 1024 + " KB");
        System.out.println("Total memory: " + 
                         runtime.totalMemory() / 1024 + " KB");
        System.out.println("Max memory: " + runtime.maxMemory() / 1024 + " KB");
    }
}

此示例演示了在分配前后进行内存监视。gc 方法建议 JVM 运行垃圾回收,但这不能保证。内存值以千字节为单位显示,以便更好地阅读。

关闭钩子

关闭钩子是已初始化但未启动的线程。JVM 在关闭之前运行它们。这种机制允许在 JVM 正常终止时进行清理操作。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        Thread shutdownHook = new Thread(() -> {
            System.out.println("Shutdown hook: Performing cleanup...");
            // Simulate cleanup
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println("Cleanup complete. Shutting down.");
        });
        
        runtime.addShutdownHook(shutdownHook);
        
        System.out.println("Application running. Press Ctrl+C to exit.");
        
        // Keep application running for demonstration
        try {
            Thread.sleep(60000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

此示例添加了一个关闭钩子,该钩子在 JVM 退出之前执行清理操作。该钩子将在应用程序正常终止时(通过完成或通过 Ctrl+C)运行。sleep 使应用程序运行足够长的时间以演示关闭钩子。

强制 JVM 退出

exit 方法通过启动其关闭序列来终止当前正在运行的 Java 虚拟机。此方法永远不会正常返回。该参数用作状态代码。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        runtime.addShutdownHook(new Thread(() -> {
            System.out.println("Shutdown hook running...");
        }));
        
        System.out.println("Application started");
        
        if (args.length > 0 && "exit".equals(args[0])) {
            System.out.println("Calling System.exit()");
            runtime.exit(0);
        }
        
        System.out.println("Application ending normally");
    }
}

此示例演示了正常终止和强制退出之间的区别。如果以“exit”作为参数运行,则 JVM 会立即退出,运行关闭钩子,但跳过 main 方法的其余部分。如果没有参数,则所有代码都会正常执行。

运行垃圾回收

gc 方法运行垃圾收集器。调用此方法表明 JVM 应努力回收未使用的对象。但是,JVM 可能会忽略此请求。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        
        System.out.println("Before allocation:");
        printMemory(runtime);
        
        // Allocate memory
        Object[] objects = new Object[10000];
        for (int i = 0; i < objects.length; i++) {
            objects[i] = new Object();
        }
        
        System.out.println("\nAfter allocation:");
        printMemory(runtime);
        
        // Null references to make objects eligible for GC
        for (int i = 0; i < objects.length; i++) {
            objects[i] = null;
        }
        
        // Suggest garbage collection
        runtime.gc();
        
        System.out.println("\nAfter GC:");
        printMemory(runtime);
    }
    
    private static void printMemory(Runtime runtime) {
        System.out.printf("Free: %d KB, Total: %d KB%n",
                         runtime.freeMemory() / 1024,
                         runtime.totalMemory() / 1024);
    }
}

此示例显示了分配之前和之后以及建议进行垃圾回收之后的内存使用情况。虽然 gc 不能保证会发生收集,但它通常会导致在不再引用对象时回收内存。

来源

Java 运行时类文档

在本文中,我们通过实际示例介绍了 Java Runtime 类的主要方法。这些方法提供了与运行时环境交互的基本功能,从执行进程到管理内存。

作者

我叫 Jan Bodnar,是一位经验丰富的程序员。我于 2007 年开始撰写编程文章,至今已撰写了超过 1,400 篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程