5.3 System和Runtime类:系统信息与运行时管理

系列 - Java API
目录
摘要
本实验学习Java中两个重要的系统级工具类:System类和Runtime类。System类部分包括:高效的数组拷贝操作、精确的时间测量方法、系统环境信息获取、以及内存垃圾回收控制;Runtime类部分涵盖:虚拟机资源信息监控(处理器数量、内存使用情况)、外部程序执行和进程管理等高级操作。
在Java编程中,有时候我们需要与"电脑系统"打交道,比如查看内存使用情况、获取系统时间、甚至启动其他程序。这时候就需要用到System类和Runtime类这两个"系统管理员"。
学习目标
通过本节学习,你将掌握:
- System类应用 - 学会数组操作、时间测量和系统信息获取
- Runtime类使用 - 掌握虚拟机监控和进程管理技巧
- 实际应用 - 能够在项目中合理使用这些系统工具
- 性能优化 - 理解如何用这些工具进行程序调优
一、System类:万能的系统助手
System类就像电脑里的"系统工具箱",提供了各种实用的功能。我们来逐一学习它的主要功能。
1. 高效的数组拷贝操作
当你需要把一个数组的一部分内容复制到另一个数组时,System.arraycopy()就像一个"高效的搬运工"。
System.arraycopy()方法参数
语法: System.arraycopy(源数组, 源起始位置, 目标数组, 目标起始位置, 拷贝长度)
参数说明:
srcArray
:源数组(从哪里拷贝)srcPos
:源数组的起始位置destArray
:目标数组(拷贝到哪里)destPos
:目标数组的起始位置length
:要拷贝的元素个数
/**
* 演示数组高效拷贝操作
*/
public class ArrayCopyDemo {
public static void main(String[] args) {
// 原始数组:存放学生分数
int[] classAScores = {85, 92, 78, 96, 88, 91, 73};
// 目标数组:用于存放优秀学生分数
int[] topStudents = new int[10];
System.out.println("原始班级成绩:");
printArray(classAScores);
// 拷贝操作:从第2个元素开始,拷贝4个元素到新数组的第1个位置
System.arraycopy(classAScores, 2, topStudents, 1, 4);
System.out.println("\n拷贝后的优秀学生数组:");
printArray(topStudents);
// 显示拷贝的具体内容
System.out.println("\n具体拷贝情况:");
System.out.println("从 classAScores[索引 2] 开始的 4 个元素:78, 96, 88, 91");
System.out.println("拷贝到 topStudents[索引 1] 开始的位置");
}
// 辅助方法:打印数组内容
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.printf("索引%d: %d ", i, array[i]);
}
System.out.println();
}
}
使用场景
- 数据迁移:大数组的部分内容转移
- 数组拼接:将多个小数组合并成大数组
- 数据备份:快速创建数组的副本
- 性能优化:比手动循环复制快得多
2. 精确的时间测量工具
当你想知道一段代码跑了多久时,System.currentTimeMillis()就像一个"精确的秒表"。
/**
* 演示程序性能测量工具
*/
public class PerformanceTimer {
public static void main(String[] args) {
System.out.println("=== 程序性能测试工具 ===");
// 测试不同的字符串拼接方式
testStringConcatenation();
// 测试数组初始化方式
testArrayInitialization();
}
/**
* 测试字符串拼接性能
*/
public static void testStringConcatenation() {
System.out.println("\n测试项目:字符串拼接性能对比");
// 记录开始时间
long startTime = System.currentTimeMillis();
// 执行要测试的操作:使用+号拼接字符串
String result = "";
for (int i = 0; i < 10000; i++) {
result += "test";
}
// 记录结束时间
long endTime = System.currentTimeMillis();
// 计算并显示执行时间
long duration = endTime - startTime;
System.out.println("使用 + 号拼接 10,000 次耗时:" + duration + "ms");
System.out.println("最终字符串长度:" + result.length());
}
/**
* 测试数组初始化性能
*/
public static void testArrayInitialization() {
System.out.println("\n测试项目:大数组初始化性能");
long startTime = System.currentTimeMillis();
// 创建并初始化一个大数组
int[] largeArray = new int[1000000];
for (int i = 0; i < largeArray.length; i++) {
largeArray[i] = i * 2;
}
long endTime = System.currentTimeMillis();
System.out.println("初始化 100万个整数的数组耗时:" + (endTime - startTime) + "ms");
System.out.println("数组的前5个元素:" + largeArray[0] + ", " + largeArray[1] + ", " + largeArray[2] + ", " + largeArray[3] + ", " + largeArray[4]);
}
}
常用的性能测量场景
- 算法效率比较:比较不同排序算法的速度
- 数据库查询时间:监控SQL语句执行耗时
- 网络请求延迟:测量API调用的响应时间
- 文件读写性能:对比不同文件操作的效率
3. 获取系统环境信息
有时候程序需要知道运行环境的信息,比如操作系统类型、Java版本等。System.getProperties()就像"系统信息查询器"。
import java.util.Properties;
/**
* 系统环境信息查询器
*/
public class SystemInfoDemo {
public static void main(String[] args) {
System.out.println("=== 系统环境信息查询 ===");
// 显示常用的系统信息
showCommonSystemInfo();
// 显示所有系统属性(可选)
// showAllSystemProperties();
}
/**
* 显示常用的系统信息
*/
public static void showCommonSystemInfo() {
System.out.println("\n--- 常用系统信息 ---");
// 获取常用的系统属性
System.out.println("操作系统名称:" + System.getProperty("os.name"));
System.out.println("操作系统版本:" + System.getProperty("os.version"));
System.out.println("用户名称:" + System.getProperty("user.name"));
System.out.println("用户主目录:" + System.getProperty("user.home"));
System.out.println("当前工作目录:" + System.getProperty("user.dir"));
System.out.println("Java版本:" + System.getProperty("java.version"));
System.out.println("Java安装目录:" + System.getProperty("java.home"));
System.out.println("文件分隔符:" + System.getProperty("file.separator"));
System.out.println("路径分隔符:" + System.getProperty("path.separator"));
}
/**
* 显示所有系统属性(了解即可)
*/
public static void showAllSystemProperties() {
System.out.println("\n--- 所有系统属性 ---");
Properties prop = System.getProperties();
// 使用增强for循环遍历所有属性
for (Object keyObj : prop.keySet()) {
String key = (String) keyObj;
String value = prop.getProperty(key);
System.out.println(key + " = " + value);
}
}
}
实际应用场景
- 跨平台开发:根据操作系统类型选择不同的处理逻辑
- 文件路径处理:使用正确的文件分隔符
- 环境检测:检查Java版本是否符合要求
- 配置管理:根据用户目录设置默认配置文件位置
4. 内存垃圾回收控制
Java会自动回收不用的内存,但有时我们希望手动"催一催"垃圾回收器工作。
/**
* 演示垃圾回收机制
*/
class Student {
private String name;
private int id;
public Student(String name, int id) {
this.name = name;
this.id = id;
System.out.println("学生 " + name + "(学号:" + id + ") 被创建了");
}
// finalize方法会在对象被垃圾回收时调用
@Override
protected void finalize() throws Throwable {
System.out.println("学生 " + name + "(学号:" + id + ") 被垃圾回收器回收了");
super.finalize();
}
}
public class GarbageCollectionDemo {
public static void main(String[] args) {
System.out.println("=== 垃圾回收机制演示 ===");
// 创建一些对象
Student student1 = new Student("张三", 001);
Student student2 = new Student("李四", 002);
Student student3 = new Student("王五", 003);
System.out.println("\n对象创建完成,现在将引用设为null...");
// 取消对象引用,使对象可以被垃圾回收
student1 = null;
student2 = null;
student3 = null;
System.out.println("调用 System.gc() 建议进行垃圾回收...");
// 建议系统进行垃圾回收(注意:只是建议,不是强制)
System.gc();
// 稍微等待一下,让垃圾回收器有机会工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序结束。");
}
}
关于垃圾回收的重要说明
- System.gc()只是建议:调用后系统可能不会立即执行垃圾回收
- finalize()不推荐使用:执行时机不确定,并且影响性能
- 实际开发中:不要依赖手动垃圾回收,Java会自动管理内存
- 合理使用:只在内存紧张时偶尔使用
二、Runtime类:虚拟机的"体检中心"
Runtime类就像Java虚拟机的"体检中心",可以查看内存使用情况、处理器信息,甚至启动其他程序。
1. 虚拟机资源监控
就像手机里的"设置"能看到存储空间使用情况一样,Runtime让你能监控Java程序的资源使用。
/**
* 虚拟机资源监控器
*/
public class VMResourceMonitor {
public static void main(String[] args) {
System.out.println("=== Java虚拟机资源监控 ===");
// 获取Runtime实例(单例模式)
Runtime runtime = Runtime.getRuntime();
// 显示系统基本信息
showSystemInfo(runtime);
// 显示内存使用情况
showMemoryUsage(runtime);
// 模拟一些内存操作后再次查看
simulateMemoryUsage(runtime);
}
/**
* 显示系统基本信息
*/
public static void showSystemInfo(Runtime runtime) {
System.out.println("\n--- 系统基本信息 ---");
System.out.println("处理器核心数:" + runtime.availableProcessors() + "个");
System.out.println("操作系统:" + System.getProperty("os.name"));
System.out.println("Java版本:" + System.getProperty("java.version"));
}
/**
* 显示内存使用情况
*/
public static void showMemoryUsage(Runtime runtime) {
System.out.println("\n--- 内存使用情况 ---");
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long maxMemory = runtime.maxMemory();
long usedMemory = totalMemory - freeMemory;
System.out.printf("已分配内存:%.2f MB\n", totalMemory / 1024.0 / 1024.0);
System.out.printf("已使用内存:%.2f MB\n", usedMemory / 1024.0 / 1024.0);
System.out.printf("空闲内存:%.2f MB\n", freeMemory / 1024.0 / 1024.0);
System.out.printf("最大可用内存:%.2f MB\n", maxMemory / 1024.0 / 1024.0);
// 计算内存使用率
double usagePercentage = (double) usedMemory / totalMemory * 100;
System.out.printf("内存使用率:%.2f%%\n", usagePercentage);
}
/**
* 模拟内存使用并监控变化
*/
public static void simulateMemoryUsage(Runtime runtime) {
System.out.println("\n--- 模拟内存操作 ---");
// 创建一个大数组来模拟内存使用
System.out.println("正在创建大数组...");
int[] largeArray = new int[1000000]; // 创建100万个整数的数组
// 再次查看内存使用情况
showMemoryUsage(runtime);
// 释放引用并建议进行垃圾回收
largeArray = null;
System.out.println("\n已释放数组引用,建议进行垃圾回收...");
runtime.gc();
// 稍微等待后再次查看
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
showMemoryUsage(runtime);
}
}
内存监控的实际应用
- 性能优化:及时发现内存泄露问题
- 资源管理:监控程序的内存使用情况
- 服务器部署:确保内存配置合理
- 调试优化:找到占用内存较多的代码段
2. 外部程序执行与管理
有时候Java程序需要调用其他程序,比如打开计算器、记事本等。Runtime.exec()就像一个"程序启动器"。
import java.io.IOException;
/**
* 外部程序执行管理器
*/
public class ProcessExecutor {
public static void main(String[] args) {
System.out.println("=== 外部程序执行演示 ===");
Runtime runtime = Runtime.getRuntime();
// 演示不同的程序启动方式
demonstrateProcessExecution(runtime);
}
/**
* 演示程序执行的不同方式
*/
public static void demonstrateProcessExecution(Runtime runtime) {
try {
System.out.println("\n1. 尝试打开记事本...");
// 根据操作系统选择不同的命令
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("windows")) {
// Windows系统打开记事本
runtime.exec("notepad.exe");
System.out.println("已在Windows上启动记事本");
} else if (osName.contains("mac")) {
// macOS系统打开文本编辑器
runtime.exec("open -a TextEdit");
System.out.println("已在macOS上启动TextEdit");
} else {
// Linux系统(可能需要根据具体发行版调整)
runtime.exec("gedit");
System.out.println("已在Linux上尝试启动gedit");
}
} catch (IOException e) {
System.out.println("程序启动失败:" + e.getMessage());
System.out.println("可能的原因:程序不存在或没有权限启动");
}
// 演示其他常用程序
demonstrateOtherPrograms(runtime);
}
/**
* 演示启动其他常用程序
*/
public static void demonstrateOtherPrograms(Runtime runtime) {
System.out.println("\n2. 其他常用程序演示:");
try {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("windows")) {
System.out.println("尝试打开计算器...");
runtime.exec("calc.exe");
} else if (osName.contains("mac")) {
System.out.println("尝试打开计算器...");
runtime.exec("open -a Calculator");
}
} catch (IOException e) {
System.out.println("程序启动失败:" + e.getMessage());
}
}
}
进程管理示例
自动关闭程序示例:
public class ProcessAutoClose {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
System.out.println("打开记事本,3秒后自动关闭...");
process = runtime.exec("notepad.exe"); // 启动记事本
Thread.sleep(3000); // 等待3秒
process.destroy(); // 关闭进程
System.out.println("记事本已自动关闭");
} catch (Exception e) {
System.out.println("操作失败:" + e.getMessage());
} finally {
// 确保进程被正确关闭
if (process != null && process.isAlive()) {
process.destroyForcibly();
}
}
}
}
安全注意事项
- 路径安全:不要执行用户输入的任意命令
- 权限控制:确保程序有执行相应命令的权限
- 资源管理:及时关闭启动的进程,避免资源泄露
- 异常处理:充分处理IOException等异常情况
学习小结
本节收获
✅ System类掌握 - 学会了数组拷贝、时间测量和系统信息获取
✅ Runtime类应用 - 掌握了虚拟机监控和进程管理技巧
✅ 性能优化 - 理解了如何用这些工具进行程序调优
✅ 实际应用 - 能够在项目中合理使用这些系统工具
关键要点:
- 📈 System类适用于:数组操作、性能测量、系统信息获取
- 🖥️ Runtime类适用于:内存监控、资源管理、进程执行
- ⚠️ 注意安全:谨慎使用进程执行功能,防止安全风险
- 🚀 实用建议:在大型项目中用于性能监控和优化
现在你已经掌握了Java系统级编程的重要工具!