Java >> Java tutorial >  >> Tag >> java.lang

Guide til java.lang.Process API

1. Introduktion

I denne selvstudie skal vi tage et dybdegående kig på processen API .

For et mere overfladisk kig på, hvordan du bruger Process for at udføre en shell-kommando, kan vi henvise til vores tidligere selvstudie her.

Processen, som den refererer til, er en eksekverende applikation. Processen klasse giver metoder til at interagere med disse processer, herunder at udtrække output, udføre input, overvåge livscyklussen, kontrollere udgangsstatus og ødelægge (dræbe) det.

2. Brug af Process Klasse til kompilering og afvikling af Java-program

Lad os se et eksempel på at kompilere og køre et andet Java-program ved hjælp af Process API:

@Test
public void whenExecutedFromAnotherProgram_thenSourceProgramOutput3() throws IOException {
 
    Process process = Runtime.getRuntime()
      .exec("javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java");
    process = Runtime.getRuntime() 
      .exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample");
    BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
    int value = Integer.parseInt(output.readLine());
 
    assertEquals(3, value);
}

Således er applikationerne til at udføre Java-kode i en eksisterende Java-kode praktisk talt ubegrænsede.

3. Oprettelse af proces

Vores Java-applikation kan bruge enhver applikation, der kører inden for vores computersystem, der er underlagt operativsystemets begrænsninger.

Derfor kan vi udføre applikationer. Lad os se, hvad de forskellige use cases vi kan køre ved at bruge Process API er.

ProcessBuilder klasse giver os mulighed for at oprette underprocesser i vores applikation.

Lad os se en demo af åbning af Windows-baseret Notepad-applikation:

ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();

4. Ødelæggelsesproces

Proces giver os også metoder til at ødelægge delprocesser eller processer. Men hvordan applikationen aflives er platformafhængig .

Lad os se forskellige use cases, som er mulige.

4.1. Ødelæggelse af en proces ved henvisning

Lad os sige, at vi bruger Windows OS og ønsker at skabe Notepad-applikationen og ødelægge den.

Som før kan vi oprette en forekomst af Notepad-applikationen ved at bruge ProcessBuilder klasse og start() metode.

Så kan vi kalde destroy() metode på vores proces objekt.

4.2. Ødelæggelse af en proces med ID

Vi kan også dræbe processer, der kører i vores operativsystem, som muligvis ikke er oprettet af vores applikation.

Vær forsigtig, mens du gør dette, da vi ubevidst kan ødelægge en kritisk proces, der kan gøre operativsystemet ustabilt .

Vi skal først finde ud af proces-id'et for den aktuelle kørende proces ved at tjekke opgavehåndteringen og finde ud af pid'en.

Lad os se et eksempel:

long pid = /* PID to kill */;
Optional<ProcessHandle> optionalProcessHandle = ProcessHandle.of(pid);
optionalProcessHandle.ifPresent(processHandle -> processHandle.destroy());

4.3. Ødelægge en proces med magt

Om udførelsen af ​​destroy() metode, vil underprocessen blive dræbt, som vi så tidligere i artiklen.

I tilfælde af destroy() ikke virker, har vi mulighed for destroyForcibly() .

Vi bør altid starte med destroy() metode først. Derefter kan vi udføre en hurtig kontrol af underprocessen, enten ved at udføre isAlive() .

Hvis det returnerer true, så kør destroyForcibly() :

ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
process.destroy();
if (process.isAlive()) {
    process.destroyForcibly();
}

5. Venter på, at en proces er fuldført

Vi har også to overbelastede metoder, hvorigennem vi kan sikre, at vi kan vente på færdiggørelsen af ​​en proces.

5.1. waitfor()

Når denne metode udføres, vil den placere den aktuelle udførelsesprocestråd i en blokerende ventetilstand, medmindre underprocessen bliver afsluttet .

Lad os tage et kig på eksemplet:

ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
assertThat(process.waitFor() >= 0);

Vi kan se fra ovenstående eksempel, at den aktuelle tråd fortsætter med at udføre den vil blive ved med at vente på, at underprocestråden slutter. Når underprocessen slutter, vil den aktuelle tråd fortsætte sin udførelse.

5.2. vent på (lang timeout, TimeUnit tid)

Når denne metode udføres, vil den placere den aktuelle udførelsesprocestråd i blokerings-vente-tilstanden, medmindre underprocessen afsluttes eller løber tør for tid .

Lad os tage et kig på eksemplet:

ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
assertFalse(process.waitFor(1, TimeUnit.SECONDS));

Vi kan se fra ovenstående eksempel, at den aktuelle tråd for at fortsætte udførelsen vil blive ved med at vente på, at underprocestråden slutter, eller hvis det angivne tidsinterval er udløbet.

Når denne metode udføres, returnerer den en boolsk værdi på sand, hvis underprocessen er afsluttet, eller en boolsk værdi, der er falsk, hvis ventetiden var gået, før underprocessen afsluttede.

6. exitValue()

Når denne metode køres, vil den aktuelle tråd ikke vente på, at underprocessen bliver afsluttet eller ødelagt, men den vil kaste en IllegalThreadStateException hvis underprocessen ikke afsluttes.

Omvendt, hvis underprocessen er blevet afsluttet, vil det resultere i en exitværdi for processen .

Det kan være et hvilket som helst muligt positivt heltal.

Lad os se på et eksempel, når exitValue() metode returnerer et positivt heltal, når underprocessen er blevet afsluttet med succes:

@Test
public void 
  givenSubProcess_whenCurrentThreadWillNotWaitIndefinitelyforSubProcessToEnd_thenProcessExitValueReturnsGrt0() 
  throws IOException {
    ProcessBuilder builder = new ProcessBuilder("notepad.exe");
    Process process = builder.start();
    assertThat(process.exitValue() >= 0);
}

7. isAlive()

Når vi gerne vil udføre forretningsbehandling, som er subjektiv, uanset om processen er i live eller ej.

Vi kan udføre en hurtig kontrol for at finde ud af, om processen er i live eller ej, hvilket returnerer en boolesk værdi.

Lad os se et hurtigt eksempel på det:

ProcessBuilder builder = new ProcessBuilder("notepad.exe");
Process process = builder.start();
Thread.sleep(10000);
process.destroy();
assertTrue(process.isAlive());

8. Håndtering af processtrømme

Som standard har den oprettede underproces ikke sin terminal eller konsol. Alle dens standard I/O-operationer (dvs. stdin, stdout, stderr) vil blive sendt til den overordnede proces. Derved kan moderprocessen bruge disse strømme til at føde input til og få output fra underprocessen.

Følgelig giver dette os en enorm mængde fleksibilitet, da det giver os kontrol over input/output af vores delproces.

8.1. getErrorStream()

Interessant nok kan vi hente de fejl, der er genereret fra underprocessen og derefter udføre forretningsbehandling.

Derefter kan vi udføre specifikke forretningsbehandlingstjek baseret på vores krav.

Lad os se et eksempel:

@Test
public void givenSubProcess_whenEncounterError_thenErrorStreamNotNull() throws IOException {
    Process process = Runtime.getRuntime().exec(
      "javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\ProcessCompilationError.java");
    BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    String errorString = error.readLine();
    assertNotNull(errorString);
}

8.2. getInputStream()

Vi kan også hente output genereret af en underproces og forbruge inden for den overordnede proces og dermed tillade dele information mellem processerne:

@Test
public void givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3() throws IOException {
    Process process = Runtime.getRuntime().exec(
      "javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java");
    process = Runtime.getRuntime()
      .exec("java -cp  src/main/java com.baeldung.java9.process.OutputStreamExample");
    BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
    int value = Integer.parseInt(output.readLine());
 
    assertEquals(3, value);
}

8.3. ge tOutputStream()

Vi kan sende input til en underproces fra en overordnet proces:

Writer w = new OutputStreamWriter(process.getOutputStream(), "UTF-8");
w.write("send to child\n");

8.4. Filtrer processtrømme

Det er en helt gyldig use-case til at interagere med selektive kørende processer.

Proces giver os mulighed for selektivt at filtrere kørende processer baseret på et bestemt prædikat.

Derefter kan vi udføre forretningsoperationer på dette selektive processæt:

@Test
public void givenRunningProcesses_whenFilterOnProcessIdRange_thenGetSelectedProcessPid() {
    assertThat(((int) ProcessHandle.allProcesses()
      .filter(ph -> (ph.pid() > 10000 && ph.pid() < 50000))
      .count()) > 0);
}

9. Konklusion

Proces er en kraftfuld klasse til interaktion på operativsystemniveau. Udløsning af terminalkommandoer samt lancering, overvågning og aflivning af applikationer.

For mere læsning om Java 9 Process API, tag et kig på vores artikel her.

Som altid finder du kilderne på Github.


Java tag