在Java中检测进程是一个常见的需求,尤其在需要与操作系统交互、监控外部程序运行状态或实现自动化任务的场景中,Java提供了多种方式来检测进程,不同的方法适用于不同的操作系统和需求场景,本文将详细介绍几种主流的实现方式,包括使用ProcessBuilder、Runtime类、操作系统特定的命令以及第三方库,并分析各自的优缺点和适用场景。

使用ProcessBuilder和Runtime类启动并监控进程
Java中最基础的进程检测方式是通过ProcessBuilder或Runtime类启动外部进程,然后通过Process对象获取进程的状态,这两种方法本质上是相同的,因为Runtime.getRuntime().exec()内部也是通过ProcessBuilder实现的。
启动进程并获取进程ID
在Windows系统中,可以通过tasklist命令列出进程,并配合findstr过滤目标进程;在Linux或macOS中,则可以使用ps命令结合grep,以下代码展示了如何在Windows系统中检测某个进程是否正在运行:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ProcessDetector {
public static boolean isProcessRunning(String processName) {
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "tasklist | findstr " + processName);
Process process = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
if (line.contains(processName)) {
return true;
}
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
String processName = "notepad.exe";
if (isProcessRunning(processName)) {
System.out.println("进程 " + processName + " 正在运行");
} else {
System.out.println("进程 " + processName + " 未运行");
}
}
}
获取进程的退出状态
通过Process.waitFor()方法可以等待进程结束,并获取其退出值,退出值为0表示进程正常结束,非0表示异常或被终止。
Process process = Runtime.getRuntime().exec("ping -n 5 127.0.0.1");
int exitCode = process.waitFor();
System.out.println("进程退出码: " + exitCode);
优缺点分析
- 优点:无需额外依赖,是Java标准库的一部分,适用于简单的进程检测需求。
- 缺点:依赖于操作系统命令,跨平台性较差;无法直接获取进程的详细信息(如CPU占用、内存使用等);频繁调用可能影响性能。
使用操作系统特定的API获取进程信息
对于更复杂的进程监控需求,可以直接调用操作系统的原生API,在Java中,可以通过JNI(Java Native Interface)调用本地方法,或者使用JNA(Java Native Access)库简化操作。
使用JNA库
JNA提供了一个简洁的框架,允许Java代码直接调用本地动态链接库(如Windows的dll或Linux的so文件),以下代码展示了如何通过JNA在Windows系统中检测进程:

添加JNA依赖(Maven):
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.12.1</version>
</dependency>
编写检测代码:
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
public class JnaProcessDetector {
public static boolean isProcessRunning(String processName) {
if (!Platform.isWindows()) {
throw new UnsupportedOperationException("仅支持Windows系统");
}
Kernel32 kernel32 = Kernel32.INSTANCE;
WinNT.PROCESSENTRY32.ByReference processEntry = new WinNT.PROCESSENTRY32.ByReference();
WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(Kernel32.TH32CS_SNAPPROCESS, 0);
try {
if (!kernel32.Process32First(snapshot, processEntry)) {
return false;
}
do {
String currentProcessName = new WString(processEntry.szExeFile).toString();
if (currentProcessName.equalsIgnoreCase(processName)) {
return true;
}
} while (kernel32.Process32Next(snapshot, processEntry));
return false;
} finally {
kernel32.CloseHandle(snapshot);
}
}
public static void main(String[] args) {
String processName = "notepad.exe";
if (isProcessRunning(processName)) {
System.out.println("进程 " + processName + " 正在运行");
} else {
System.out.println("进程 " + processName + " 未运行");
}
}
}
优缺点分析
- 优点:跨平台性较好(通过JNA支持Windows、Linux、macOS);可以获取详细的进程信息(如进程ID、内存占用、句柄等)。
- 缺点:需要引入第三方库;代码复杂度较高;不同操作系统的API差异可能需要额外处理。
使用第三方库实现高级进程监控
除了JNA,还有一些专门用于进程监控的第三方库,如oshi和sigar,这些库封装了操作系统的底层API,提供了更简洁的接口。
使用oshi库
Oshi是一个跨平台的系统信息库,可以轻松获取进程、内存、CPU等信息,首先添加依赖:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>6.4.0</version>
</dependency>
然后编写检测代码:

import oshi.SystemInfo;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;
import java.util.List;
public class OshiProcessDetector {
public static boolean isProcessRunning(String processName) {
SystemInfo systemInfo = new SystemInfo();
OperatingSystem os = systemInfo.getOperatingSystem();
List<OSProcess> processes = os.getProcesses(null, null);
for (OSProcess process : processes) {
if (process.getName().equalsIgnoreCase(processName)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
String processName = "notepad.exe";
if (isProcessRunning(processName)) {
System.out.println("进程 " + processName + " 正在运行");
} else {
System.out.println("进程 " + processName + " 未运行");
}
}
}
优缺点分析
- 优点:跨平台支持良好;接口简洁,易于使用;可以获取丰富的系统信息(如进程的CPU占用、内存占用、父进程ID等)。
- 缺点:库体积较大,可能增加应用的内存占用;对于极轻量级的进程检测需求可能显得过于复杂。
跨平台进程检测的最佳实践
在实际开发中,选择哪种方法取决于具体需求:
- 简单场景:如果只是需要检测某个进程是否存在,且对跨平台性要求不高,使用
ProcessBuilder或Runtime类即可。 - 需要详细信息:如果需要获取进程的CPU、内存等详细信息,推荐使用
oshi或JNA库。 - 高性能需求:如果需要频繁监控大量进程,建议使用
JNA直接调用系统API,以减少性能开销。
需要注意以下几点:
- 权限问题:在Linux或macOS中,可能需要管理员权限才能获取所有进程的信息。
- 进程名称匹配:不同操作系统中进程名称的格式可能不同(如Windows中是
notepad.exe,Linux中可能是notepad),需要根据实际情况调整匹配逻辑。 - 异常处理:调用外部命令或本地API时,需要妥善处理异常,避免程序崩溃。
Java检测进程的方法多种多样,从简单的命令调用到复杂的本地API封装,开发者可以根据实际需求选择合适的方案,对于简单的进程存在性检测,ProcessBuilder和Runtime类足够使用;而对于需要详细进程信息或跨平台支持的场景,oshi或JNA库则是更好的选择,无论采用哪种方法,都需要注意跨平台兼容性、权限管理和异常处理,以确保程序的稳定性和可靠性。


















