Process-與操作系統(tǒng)中的進(jìn)程進(jìn)行交互
1、Process介紹
在Java中,Process類是一個抽象類,它提供了與操作系統(tǒng)中的進(jìn)程進(jìn)行交互的方法。當(dāng)你在Java程序中啟動一個新的進(jìn)程(例如,運(yùn)行一個外部程序或腳本)時(shí),JVM會創(chuàng)建一個Process實(shí)例來代表這個新的進(jìn)程。
Process類提供了以下主要的方法:
- getInputStream():獲取進(jìn)程的標(biāo)準(zhǔn)輸出流。你可以從這個流中讀取進(jìn)程的輸出。
- getErrorStream():獲取進(jìn)程的錯誤輸出流。你可以從這個流中讀取進(jìn)程的錯誤輸出。
- getOutputStream():獲取進(jìn)程的標(biāo)準(zhǔn)輸入流。你可以向這個流中寫入數(shù)據(jù),作為進(jìn)程的輸入。
- waitFor():等待進(jìn)程結(jié)束,并返回進(jìn)程的退出狀態(tài)碼。
- exitValue():獲取進(jìn)程的退出狀態(tài)碼。如果進(jìn)程還沒有結(jié)束,這個方法會拋出IllegalThreadStateException。
- destroy():強(qiáng)制結(jié)束進(jìn)程。
以下是一個使用Process類的例子,它啟動一個新的進(jìn)程來運(yùn)行ping命令:
Process process = Runtime.getRuntime().exec("ping www.google.com");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
process.waitFor();
在這個例子中,我們首先使用Runtime.exec方法啟動一個新的進(jìn)程來運(yùn)行ping命令。然后,我們創(chuàng)建一個BufferedReader來讀取進(jìn)程的輸出。最后,我們使用Process.waitFor方法等待進(jìn)程結(jié)束。
2、使用
- 使用Runtime.getRuntime().exec("java -c"),相當(dāng)于調(diào)用三方庫(三方程序)
- Runtime.getRuntime().exec()
Runtime.getRuntime().exec(參數(shù)1)
參數(shù)1是:執(zhí)行的命令
Runtime.getRuntime().exec(參數(shù)1,參數(shù)2,參數(shù)3)
參數(shù)1是:執(zhí)行的命令
參數(shù)3是:程序執(zhí)行的文件夾,如:/phantomjs211/linux/bin
3、獲取執(zhí)行進(jìn)程的pid(jdk8)
3.0、Java 9及更高版本,可以直接獲取。
Process process = Runtime.getRuntime().exec("some-command");
long pid = process.pid();
System.out.println("PID: " + pid);
3.1、JNA、JNA和Process
- Java Native Access (JNA)庫
Java Native Access (JNA) 是一個開源的Java庫,它允許Java程序調(diào)用C和C++編寫的本地應(yīng)用程序接口(API)和庫,而無需使用Java Native Interface (JNI) 或編寫任何本地代碼。
在傳統(tǒng)的JNI使用中,Java開發(fā)者需要編寫本地方法的Java聲明,然后使用特定的工具生成C或C++的頭文件,接著在這些頭文件中實(shí)現(xiàn)本地方法。這個過程相當(dāng)復(fù)雜,需要對C或C++有一定的了解,而且還需要處理本地代碼的編譯和分發(fā)。
相比之下,JNA大大簡化了這個過程。使用JNA,你只需要在Java代碼中聲明本地方法的接口,然后JNA會自動處理與本地代碼的交互,包括參數(shù)的轉(zhuǎn)換和內(nèi)存的管理。這意味著你可以直接在Java代碼中調(diào)用本地方法,而無需編寫或理解任何C或C++代碼。
例如,假設(shè)你有一個C庫,它提供了一個名為doSomething的函數(shù)。在JNI中,你需要編寫C代碼來實(shí)現(xiàn)一個與doSomething對應(yīng)的本地方法。但在JNA中,你只需要聲明一個接口,如下所示:
- JNA和Process的關(guān)系、區(qū)別
Process類和Java Native Access (JNA)庫都是Java中與本地系統(tǒng)交互的方式,但它們的用途和工作方式有所不同。
Process類是Java標(biāo)準(zhǔn)庫的一部分,它用于創(chuàng)建和控制操作系統(tǒng)的進(jìn)程。你可以使用Process類來執(zhí)行外部命令,然后獲取命令的輸出或錯誤信息,或者控制命令的輸入。Process類提供了一種簡單的方式來與操作系統(tǒng)的shell交互,但它的功能相對有限,主要限于啟動新的進(jìn)程和與這些進(jìn)程進(jìn)行簡單的交互。
Java Native Access (JNA)庫則提供了一種更直接和強(qiáng)大的方式來與本地系統(tǒng)交互。使用JNA,你可以直接調(diào)用操作系統(tǒng)的API,或者使用其他本地庫。這意味著你可以在Java代碼中使用本地系統(tǒng)的所有功能,而不僅僅是啟動新的進(jìn)程。然而,使用JNA通常需要對本地系統(tǒng)的API有一定的了解,而且JNA的使用也比Process類更復(fù)雜。
總的來說,Process類和JNA庫都是Java中與本地系統(tǒng)交互的工具,但它們的功能和使用場景有所不同。
Process類主要用于啟動和控制新的進(jìn)程,而JNA庫則提供了一種更直接和強(qiáng)大的方式來使用本地系統(tǒng)的API和庫。
3.2、導(dǎo)包(gradle)
// implementation 'net.java.dev.jna:jna:5.12.1'
implementation 'net.java.dev.jna:jna-platform:5.12.1'
3.3、工具類-測試
package com.cc.urlgethtml.utils;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.Objects;
import java.util.Optional;
/**
* <p>JnaPlatform:獲取執(zhí)行命令的pid</p>
*
* @author CC
* @since 2023/11/6
*/
public class JnaPlatform {
public static void main(String[] args) {
Process process = null;
try {
//執(zhí)行命令
if (Platform.isWindows()) {
process = Runtime.getRuntime().exec("java -version", new String[]{},
new File("D:\\"));
}else {
process = Runtime.getRuntime().exec("ls -l");
}
//獲取日志
InputStream inputStream = process.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String msg;
while ((msg = reader.readLine()) != null) {
System.out.println(msg);
}
//獲取pid
Optional<Integer> pid = getPid(process);
System.out.println("pid----" + pid.orElse(-1));
}catch(Exception e){
throw new RuntimeException(e.getMessage());
}finally {
if (Objects.nonNull(process)) {
process.destroy();
}
}
}
/** <p>獲取pid<p>
* @param process process
* @return {@link Optional<Integer>}
* @since 2023/11/6
* @author CC
**/
public static Optional<Integer> getPid(Process process) {
if (Platform.isLinux()) {
/* Linux platform */
try {
Field pidField = process.getClass().getDeclaredField("pid");
pidField.setAccessible(true);
return Optional.of((Integer) pidField.get(process));
} catch (NoSuchFieldException | IllegalAccessException e) {
return Optional.empty();
}
} else if (Platform.isWindows()) {
/* Windows platform */
try {
Field handleField = process.getClass().getDeclaredField("handle");
handleField.setAccessible(true);
long handl = (Long) handleField.get(process);
Kernel32 kernel = Kernel32.INSTANCE;
WinNT.HANDLE hand = new WinNT.HANDLE();
hand.setPointer(Pointer.createConstant(handl));
int pid = kernel.GetProcessId(hand);
return Optional.of(pid);
} catch (NoSuchFieldException | IllegalAccessException e) {
return Optional.empty();
}
}
return Optional.empty();
}
/** <p>根據(jù)pid停止進(jìn)程-待實(shí)現(xiàn)<p>
* @since 2023/11/6
* @author CC
**/
public boolean kill(String pId){
return true;
}
}
- 結(jié)果

浙公網(wǎng)安備 33010602011771號