Kapcsolat a külvilággal

A cikk a haladóbb Java programozóknak szól, akiknek a Runtime meg Process, és az összes hasonló magasröptű és elvont Java fogalom ismerős vibrálásokat okoz, viszont akiknek még nem volt alkalmuk elmélyedni a Java eme ágazatában.

Sokszor előfordulhat egy programozó életében (még egy Java programozóéban is) hogy bizony egy másik programot le kell futtatni, és annak a bemeneti adatait feldolgozni. A rendszerközeli programozási technológiák (Windows alatt a Win32 API, Unix alatt pld a C exec*  parancsai) mind jönnek egy-egy megoldással erre a problémára, és ezek a natív C megoldások általában nagyon könnyen átültethetőek egy más (gép natív) programozási nyelvbe, például a Delphi is tudja használni a Win32 API hívásokat.

A Java esetében más a helyzet. Egy java programozó általában nagyon keveset tud a rendszer sajátosságairól, és a natív kód használata (általában) veszélyezteti a program portálhatóságát.

A Java programozónak egyetlen kapcsolata a külvilággal a Runtime osztály, amelyből egyetlen darab singleton típusú objektum van példányosítva. Ez az objektum automatikusan létrejön a java program indításakor, és nem lehet más Runtime példányokat létrehozni. Rengeteg hasznos függvényéből most csak egy párat sorolok fel, azokat, melyeket a mindennapi munkába is hasznosnak találtam. Persze, ez még nem ok arra, hogy a tisztelt olvasó ne nézzen utána annak, ami kimaradt.

Egy pár Runtime függvény

static Runtime getRuntime() - visszatéríti a rendszer Runtime objektumát, minden más Runtime függvényhívást ennek a függvénynek a visszatérési értékével kell végrehajtanunk.

void gc() - ha úgy érezzük, hogy betelt a memóriánk, akkor „soron kívül” meg tudjuk hívni a szemétgyűjtést, hogy szabadítsa fel a már nem használt memóriát. Ez különösen hasznos, ha olyan platformra fejlesztünk, ahol aránylag korlátozott a memória mérete (Pld, a J2ME (A mobiltelefonok Java fejlesztőkörnyezete) 64K heap memóriát képes csak kezelni. Ezen esetbe igencsak oda kell figyelnünk, hogy mit hagyunk a memóriába).

long freeMemory() - ez a függvény visszatéríti a szabad memória méretét, byte-okban mérve. Ez valójában a rendszer szabad memóriamérete, nem a java virtuális gépé.

long totalMemory() - visszatéríti a Java virtuális gép összes memóriaméretét.

Process exec(-) - az exec család függvényei mind ugyanazt a célt szolgálják. Végrehajtanak egy programot a rendszeren, és egy Process objektummal térnek vissza.

Az exec(-) függvény nem lesz minden alkalommal sikeres- Például sikertelen, ha olyan programot akarunk végrehajtani, amely az operációs rendszer natív ablakkezelési rutinjait használja. Szintén sikertelen lesz, ha Unix/linux daemon processzt akarunk elindítani, vagy Win32 alatt régi DOS vagy Win16 programokat végrehajtani. A Shell scripteket se szereti.

Következtetésképpen: egyszerű parancssoros programok futására ideális, a többit viszont inkább ne piszkáljuk. A Process objektum által képviselt program futhat párhuzamosan a Java programmal, és nem kötelező kilépnie akkor, amikor a Java program befejeződik.

Egy Java program megvárhatja az általa létrehozott program befejeződését a Process.waitFor() metódussal. Ennek a visszatérési értéke egy int, amely hiba esetén nem nulla. Egy Java program ki is nyírhatja az általa elindított programot a destroy() metódussal.

Talán a két legfontosabb tulajdonsága a Process objektumnak az, hogy le tudja kérni a futó program standard Input/Output streamjeit, és így tud kommunikálni a futó programmal. Erre az OutputStream getOutputStream() illetve InputStream getInputStream() metódusokat lehet használni. Ugyanilyen módon le lehet kérni az Error Streamet is. A futó program output streamjét a java program input streamjébe kell beágyazni, illetve fordítva, az input streamet a java program output streamjébe.

A következő program nem csinál mást, mint bemutatja a fent leirt elmélet gyakorlati részét, vagyis végrehajt egy parancsot a rendszeren, esetünkbe egy egyszerű „ls” parancsot.:

import java.io.*;

public class TestRuntime{

   public static void main(String[] args) {

        try {

            Runtime runtime = Runtime.getRuntime();

            String command = "ls";

            Process process =runtime.exec(command);

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

                      String line = null;

                      while( (line = reader.readLine()) != null) {

                  System.out.println(line);

           }

                    process.waitFor();

        }

        catch (SecurityException e) {

            System.out.println("Caught security exception trying to run an underlying UNIX program");

        }

        catch (IOException ioe) {

            System.out.println("Caught i/o exception in exec");

        }

        catch(Exception ex) {

                System.out.println("Unknown ex");

        }

   }

}

A programot bárki használhatja saját és üzleti céljára, illetve módosíthatja is. A mechanizmus optimális esetekben egy Applet-ből is működőképes.

Deák Ferenc - deak.ferenc@miskolc.evosoft.hu