fbpx

Process API újítások

Előzmények

A Java korai verzióiban elég nehézkes volt új folyamatot indítani. Ehhez csak a Runtime.getRuntime().exec() metódus állt rendelkezésünkre. 2004-ben, a Java 5 megjelenésével ez megváltozott, innentől kezdve elérhetővé vált a ProcessBuilder API, amivel könnyebben lehetett létrehozni új folyamatokat. Nézzük meg, hogy mivel bővül a process API repertoárja a Java 9-ben!

process API szemléltetésére szolgáló ábra

ProcessHandle interfész

Az új ProcessHandle interfész új lehetőségeket nyit számunkra a natív folyamatok kezeléséhez. A Java 5 óta elérhető ProcessBuilder által előállított Process objektumoktól elkérhető azok ProcessHandle-je.

A ProcessHandle feladata, hogy azonosítson egy folyamatot és lehetővé tegye, hogy különféle műveleteket végezzünk el rajta. Példányok a következő statikus factory metódusok segítségével hozhatók létre:

Statikus factory metódus Létrehozott ProcessHandle objektum
current() Az aktuális folyamathoz tartozó ProcessHandle objektummal tér vissza.
of(long pid) Optional<ProcessHandle> objektummal tér vissza, ami a megadott natív folyamat azonosítóhoz tartozik.
children() Stream<ProcessHandle> objektummal tér vissza, ami az aktuális folyamathoz tartozó közvetlen gyerek folyamatokat tartalmazza.
descendants() Stream<ProcessHandle> objektummal tér vissza, ami az aktuális folyamathoz tartozó gyerek folyamatokat tartalmazza, rekurzívan azok gyerek folyamataival együtt.
parent() Optional<ProcessHandle> objektummal tér vissza, ami az aktuális folyamat szülő folyamatát tartalmazza.
allProcesses() Egy olyan Stream<ProcessHandle> objektummal tér vissza, ami az aktuális folyamat által látható össze folyamat ProcessHandle-jét tartalmazza.

További hasznos metódusok, amit a ProcessHandle interfész elérhetővé tesz:

ProcessHandle metódus Leírás
info() ProcessHandle.Info objektummal tér vissza, ami az adott folyamathoz tartozó információkat tartalmazza.
isAlive() boolean-nel tér vissza, ami azt jelzi, hogy az adott folyamat él-e még.
pid() A natív folyamat azonosítóval tér vissza, ami alapján az operációs rendszer számon tartja az adott folyamatot.
supportsNormalTermination() boolean-nel tér vissza, ami azt jelzi, hogy támogatja-e a normál leállítást az adott folyamat, vagy rákényszerítve, azonnal állítja le a folyamatot.
onExit() CompletableFuture<ProcessHandle> objektummal tér vissza, ami arra használható, hogy az adott folyamat befejeződésekor, szinkron vagy szinkron módon, elindítsunk egy tetszőleges utasítást.
destroy() boolean-nel tér vissza, ami azt mutatja meg, hogy az adott folyamat leállítási kérelme sikeresen fel lett-e dolgozva.

ProcessHandle.Info interfész

Egy folyamatra egy adott időpillanatban vonatkozó információit tartalmazza. Ezek az információk korlátozottak lehetnek az információkat igénylő folyamatra vonatkozó operációs rendszeri jogosultságok függvényében.

ProcessHandle.Info metódus Leírás
arguments() Az adott folyamat argumentumait tartalmazó String tömböt tartalmazó Optional objektummal tér vissza.
command() Az adott folyamathoz tartozó alkalmazás nevét tartalmazó Optional-lel tér vissza.
commandLine() Az adott folyamathoz tartozó parancssort tartalmazó Optional-lel tér vissza.
startInstant() Az adott folyamat indításának pillanatát tartalmazó Optional-lel tér vissza.
totalCpuDuration() Az adott folyamat által felhasznált CPU-időt tartalmazó Optional-lel tér vissza.
user() Az adott folyamat felhasználóját tartalmazó Optional-lel tér vissza.

Példa

public static void main(String[] args) throws InterruptedException, IOException {
    printProcessInfo("main", ProcessHandle.current());
    Process process = new ProcessBuilder("notepad.exe", "C:/teszt.txt").start();
    printProcessInfo("notepad", process.toHandle());
    process.waitFor();
    printProcessInfo("notepad", process.toHandle());
}

private static void printProcessInfo(String processDescription, ProcessHandle processHandle) {
    System.out.println("---------- Információk a(z) " + processDescription + " folyamatról ----------");
    System.out.printf("Folyamat azonosító (PID): %d%n", processHandle.pid());
    ProcessHandle.Info info = processHandle.info();
    System.out.printf("Parancs: %s%n", info.command().orElse(""));
    String[] arguments = info.arguments().orElse(new String[] {});
    System.out.println("Argumentumok:");
    for (String argument : arguments) {
        System.out.printf("   %s%n", argument);
    }
    System.out.printf("Parancssor: %s%n", info.commandLine().orElse(""));
    System.out.printf("Indítási idő: %s%n", info.startInstant().orElse(Instant.now()).toString());
    System.out.printf("Futási idő: %sms%n", info.totalCpuDuration().orElse(Duration.ofMillis(0)).toMillis());
    System.out.printf("Felhasználó: %s%n", info.user().orElse(""));
    System.out.println();
}

Összefoglalás

A Java 9 process API újításai segítségével szebb kódot írhatunk. A korábbi verzióban bevezetett ProcessBuilder is jelentős lépés volt a helyes irányba, de az új lehetőségek, amiket az új interfészek, illetve az azokat megvalósító osztályok biztosítanak, fontos új eszközöket adnak a programozók kezébe, amikkel könnyebben kezelhetővé váltak a natív folyamatok.

Ha a többi Java 9-es újítás is érdekel, akkor böngészd bátran a többi blog posztot is ebben a témában!

A hivatalos javadoc-ban minden további részletet megtalálsz:

ProcessBuilder, Process, ProcessHandle, ProcessHandle.Info, CompletableFuture.

Ha tetszett, oszd meg!

Szólj hozzá!