Gids voor java.lang.Process API

1. Inleiding

In deze tutorial gaan we nemen een diepgaande blik op de Werkwijze API.

Voor een ondieper onderzoek hoe te gebruiken Werkwijze om een ​​shell-commando uit te voeren, kunnen we hier naar onze vorige tutorial verwijzen.

Het proces waarnaar het verwijst, is een uitvoerende applicatie. De Werkwijze class biedt methoden voor interactie met deze processen, waaronder het extraheren van uitvoer, het uitvoeren van invoer, het bewaken van de levenscyclus, het controleren van de uitgangsstatus en het vernietigen (doden) ervan.

2. Met behulp van Werkwijze Klasse voor het compileren en uitvoeren van Java-programma

Laten we een voorbeeld bekijken om een ​​ander Java-programma te compileren en uit te voeren met behulp van Werkwijze API:

@Test public void whenExecutedFromAnotherProgram_thenSourceProgramOutput3 () gooit 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 = nieuwe BufferedReader (nieuwe InputStreamReader (process.getInputStream ())); int waarde = Integer.parseInt (output.readLine ()); assertEquals (3, waarde); }

De toepassingen voor het uitvoeren van Java-code binnen een bestaande Java-code zijn dus vrijwel onbeperkt.

3. Creëren proces

Onze Java-applicatie kan elke applicatie aanroepen die binnen ons computersysteem wordt uitgevoerd, afhankelijk van de beperkingen van het besturingssysteem.

Daarom kunnen we applicaties uitvoeren. Laten we eens kijken wat de verschillende use-cases zijn die we kunnen uitvoeren door de Process API te gebruiken.

De ProcessBuilder class stelt ons in staat om subprocessen te creëren binnen onze applicatie.

Laten we een demo bekijken van het openen van de Windows-gebaseerde Kladblok-applicatie:

ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start ();

4. Vernietigingsproces

Werkwijze biedt ons ook methoden om subprocessen of processen te vernietigen. Hoewel de manier waarop de applicatie wordt gedood, platformafhankelijk is.

Laten we eens kijken naar verschillende use-cases die mogelijk zijn.

4.1. Een proces vernietigen door middel van verwijzing

Laten we zeggen dat we Windows OS gebruiken en de Kladblok-applicatie willen spawnen en vernietigen.

Zoals eerder kunnen we een exemplaar van de Kladblok-toepassing maken met behulp van de ProcessBuilder klasse en de begin() methode.

Dan kunnen we de vernietigen() methode op onze Werkwijze voorwerp.

4.2. Een proces vernietigen op basis van ID

We kunnen ook processen beëindigen die binnen ons besturingssysteem worden uitgevoerd en die mogelijk niet door onze applicatie zijn gemaakt.

Voorzichtigheid is geboden wanneer u dit doet, omdat we onbewust een kritiek proces kunnen vernietigen waardoor het besturingssysteem onstabiel kan worden.

We moeten eerst de proces-ID van het huidige actieve proces achterhalen door de taakbeheerder te controleren en de pid te achterhalen.

Laten we een voorbeeld bekijken:

Optioneel optioneelProcessHandle = ProcessHandle.of (5232); optionalProcessHandle.ifPresent (processHandle -> processHandle.destroy ()); 

4.3. Een proces met geweld vernietigen

Over de uitvoering van de vernietigen() methode, wordt het subproces gedood zoals we eerder in het artikel zagen.

In het geval dat vernietigen() werkt niet, we hebben de optie van met geweld vernietigen.

We moeten altijd beginnen met vernietigen() methode eerst. Daarna kunnen we een snelle controle van het subproces uitvoeren door uit te voeren is levend().

Als het true retourneert, voer dan uit met geweld vernietigen:

ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start (); process.destroy (); if (process.isAlive ()) {process.destroyForcibly (); }

5. Wachten tot een proces is voltooid

We hebben ook twee overbelaste methoden, waarmee we ervoor kunnen zorgen dat we kunnen wachten op voltooiing van een proces.

5.1. wachten op()

Wanneer deze methode wordt uitgevoerd, wordt deze geplaatst de huidige thread van het uitvoeringsproces in een blocking-wait-status, tenzij het subproces wordt beëindigd.

Laten we het voorbeeld eens bekijken:

ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start (); assertThat (process.waitFor ()> = 0); 

We kunnen uit het bovenstaande voorbeeld zien dat de huidige thread doorgaat met uitvoeren, hij zal blijven wachten tot de subproces-thread is beëindigd. Zodra het subproces is beëindigd, gaat de huidige thread door met zijn uitvoering.

5.2. waitfor (lange timeOut, TimeUnit tijd)

Wanneer deze methode wordt uitgevoerd, wordt deze geplaatst de huidige thread van het uitvoeringsproces in de blocking-wait-status, tenzij het subproces wordt beëindigd of geen tijd meer heeft.

Laten we het voorbeeld eens bekijken:

ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start (); assertFalse (process.waitFor (1, TimeUnit.SECONDS));

We kunnen aan de hand van het bovenstaande voorbeeld zien dat de huidige thread doorgaat met uitvoeren, hij zal blijven wachten tot de thread van het subproces is beëindigd of dat het opgegeven tijdsinterval is verstreken.

Wanneer deze methode wordt uitgevoerd, wordt de booleaanse waarde true geretourneerd als het subproces is afgesloten, of een booleaanse waarde false als de wachttijd is verstreken voordat het subproces is afgesloten.

6. exitValue ()

Wanneer deze methode wordt uitgevoerd, wacht de huidige thread niet tot het subproces is beëindigd of vernietigd, maar het genereert een IllegalThreadStateException als het subproces niet wordt beëindigd.

Een andere manier om het subproces met succes te beëindigen, resulteert in een exitwaarde van het proces.

Het kan elk mogelijk positief geheel getal zijn.

Laten we naar een voorbeeld kijken wanneer de exitValue () methode retourneert een positief geheel getal als het subproces succesvol is beëindigd:

@Test openbare ongeldig gegevenSubProcess_whenCurrentThreadWillNotWaitIndefinitelyforSubProcessToEnd_thenProcessExitValueReturnsGrt0 () gooit IOException {ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start (); assertThat (process.exitValue ()> = 0); }

7. is levend()

Wanneer we zakelijke verwerking willen uitvoeren die subjectief is, of het proces nu leeft of niet.

We kunnen een snelle controle uitvoeren om te zien of het proces actief is of niet, wat een booleaanse waarde retourneert.

Laten we er een snel voorbeeld van bekijken:

ProcessBuilder builder = nieuwe ProcessBuilder ("notepad.exe"); Proces proces = builder.start (); Thread.sleep (10000); process.destroy (); assertTrue (process.isAlive ());

8. Omgaan met processtromen

Standaard heeft het aangemaakte subproces geen terminal of console. Alle standaard I / O-bewerkingen (d.w.z. stdin, stdout, stderr) worden naar het bovenliggende proces gestuurd. Daardoor kan het ouderproces deze stromen gebruiken om input te voeden en output te krijgen van het subproces.

Dit geeft ons dan ook een enorme mate van flexibiliteit omdat het ons controle geeft over de input / output van ons subproces.

8.1. getErrorStream ()

Interessant is dat we de fouten die uit het subproces zijn gegenereerd, kunnen ophalen en daarop zakelijke verwerking kunnen uitvoeren.

Daarna kunnen we specifieke bedrijfscontroles uitvoeren op basis van onze vereisten.

Laten we een voorbeeld bekijken:

@Test openbare ongeldige gegevenSubProcess_whenEncounterError_thenErrorStreamNotNull () genereert IOException {Process process = Runtime.getRuntime (). Exec ("javac -cp src \ main \ java \ com \ baeldung \ java9 \ process \ ProcessCompilation \ ProcessCompilation "); BufferedReader-fout = nieuwe BufferedReader (nieuwe InputStreamReader (process.getErrorStream ())); Tekenreeks errorString = error.readLine (); assertNotNull (errorString); }

8.2. getInputStream ()

We kunnen ook de output ophalen die wordt gegenereerd door een subproces en consumeren binnen het bovenliggende proces, waardoor we informatie kunnen delen tussen de processen:

@Test openbare ongeldige gegevenSourceProgram_whenReadingInputStream_thenFirstLineEquals3 () gooit IOException {Process process = Runtime.getRuntime (). Exec ("javac -cp src src \ main \ java \ com \ baeldung \ java9 \ process \ output \ "); process = Runtime.getRuntime () .exec ("java -cp src / main / java com.baeldung.java9.process.OutputStreamExample"); BufferedReader output = nieuwe BufferedReader (nieuwe InputStreamReader (process.getInputStream ())); int waarde = Integer.parseInt (output.readLine ()); assertEquals (3, waarde); }

8.3. getOutputStream ()

We kunnen input naar een subproces sturen vanuit een bovenliggend proces:

Writer w = nieuwe OutputStreamWriter (process.getOutputStream (), "UTF-8"); w.write ("stuur naar kind \ n");

8,4. Filter processtromen

Het is een perfect geldige use-case om te communiceren met selectieve lopende processen.

Werkwijze biedt ons de mogelijkheid om lopende processen selectief te filteren op basis van een bepaald predikaat.

Daarna kunnen we bedrijfsactiviteiten uitvoeren op deze selectieve processet:

@Test openbare ongeldig gegevenRunningProcesses_whenFilterOnProcessIdRange_thenGetSelectedProcessPid () {assertThat (((int) ProcessHandle.allProcesses () .filter (ph -> (ph.pid ()> 10000 && ph.pid () 0);}

9. Conclusie

Werkwijze is een krachtige klasse voor interactie op besturingssysteemniveau. Het activeren van terminalopdrachten en het starten, bewaken en doden van applicaties.

Bekijk ons ​​artikel hier voor meer informatie over de Java 9 Process API.

Zoals altijd vind je de bronnen op Github.