Gyakorlati alapok III.
A Runtime osztály
Ebben a fejezetben egy, magasabb szinten már igen fontos osztállyal fogunk megismerkedni. Lokációja a Java.lang csomagban található, neve Runtime (Java.lang.Runtime). Minden futó Java-alkalmazásnak van egy, ebből az osztályból származó példánya, amely aktív és jól átjárható hidat képez az alkalmazás és a futtató környezet, tehát maga a JVM felé. Ennek vizsgálatához először létre kell hoznunk egy “élő, lélegző” Runtime-objektumot, amelyet a következőképpen tehetünk meg:
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
}
}
Végeredmény:
Az objektum létrejött, de nem csinál semmit
Ezután kulcsfontosságú metódusokhoz férhetünk hozzá, ilyen például az
exit(), amely segítségével "angol eleganciával",
azaz minden további kérdezés nélkül, de azért viszonylagos szabályozottsággal
kapcsolhatjuk le az éppen futó Java-alkalmazásunkat:
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("A kovetkezo lepes az exit().");
runtime.exit(0);
System.out.println("Ez mar soha nem fut le.");
}
}
Végeredmény:
A kovetkezo lepes az exit().
Láthatjuk, hogy az exit() utáni programlépés sohasem fog végrehajtásra kerülni.
A Runtime segítségével az exit() metódusnál jóval brutálisabb leállítási metódus is rendelkezésre áll, ez a halt(). Azonban míg az exit() metódus figyelembe vesz bizonyos lezárási és időzítési folyamatokat, addig a halt() nem, ezért használata fokozott óvatosságot igényel!
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("A kovetkezo lepes a halt().");
runtime.halt(0);
System.out.println("Ez mar soha nem fut le.");
}
}
Végeredmény:
A kovetkezo lepes a halt().
Láthatjuk, hogy a halt() utáni programlépés sohasem fog végrehajtásra kerülni.
Közvetlenül elérhető a kódeltakarító gc() metódus
is (garbage collector - Runtime.gc()),
amelyről részletesen írtunk A részlegesen destruktív magatartás: a virtuális
szemétgyűjtés című fejezetben:
"A szemétsöprés rutinjára közvetlenül is hivatkozhatunk a System.gc() vagy Runtime.gc() metódushívásokkal. Ez azonban (a legjobb tudomásom szerint) pusztán egy kérés, "ajánlás" a rendszer felé, ezért a tisztítási folyamat nem fog beindulni azonnal; a virtuális kukásautó érkezésének tényleges időpontjáról a JVM fog dönteni. Valószínűnek tartom, hogy a rendszer folyamatosan figyeli a terhelhetőséget, a memóriahasználat mértékét, stb., azaz minden olyan tényezőt, amely hatással lehet a futási teljesítményre és a szemétgyűjtést üresjárati időben vagy ehhez hasonló állapotokban indítja be."
Bizonyítékul, miszerint milyen fontos objektumhoz jutottunk hozzá, nézzük meg néhány további beépített metódusát!
A JVM rendelkezésére álló teljes (és tegyük hozzá: az aktuális futtatási környezettől függő) memóriamennyiség bájtban mérve (totalMemory()):
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.totalMemory());
}
}
Végeredmény:
1289744848
A szabad (és tegyük hozzá: az aktuális futtatási környezettől függő) memóriamennyiség a JVM-ben bájtban (freeMemory()):
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.freeMemory());
}
}
Végeredmény:
127611672
A JVM által maximálisan felhasználható (és tegyük hozzá: az aktuális futtatási környezettől függő) memóriamennyiség bájtban (maxMemory()):
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.maxMemory());
}
}
Végeredmény:
1897922560
A JVM által aktuálisan elérhető processzorok száma (availableProcessors()):
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println(runtime.availableProcessors());
}
}
Végeredmény:
4
Sőt, kezdeményezhetünk önálló programfuttatást is, erről az exec() metódus és variánsai gondoskodnak. Sokszor, de nem minden esetben a függvény paramétereként az indítandó alkalmazás elérési útját kell megadnunk. Az alábbiakban én a Google Chrome böngészőt indítottam. Mivel egy alkalmazás indítása mindig elég kényes mozzanat sok-sok hibalehetőséggel, a lényegi kódrészt kötelezően try-catch blokkba kell tennünk.
Figyelem!
Ügyeljünk az elérési út pontos megadására!
Az alkalmazás elérési útja rendszertől függően változhat!
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("\"C:\\Program Files
(x86)\\Google\\Chrome\\Application/chrome.exe\"");
System.out.println("Google Chrome
inditva!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Végeredmény:
Google Chrome inditva!
Néhány alkalmazás elérési út megadása nélkül is indítható, ilyen például a Jegyzettömb (Win10 Notepad):
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
try {
runtime.exec("notepad.exe");
System.out.println("Notepad
inditva!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Végeredmény:
Notepad inditva!
Ugyanilyen módon, ugyanerről a helyről (C:\\Windows\) indítható a Win10 Wordpad is (write.exe), azonban a velük azonos könyvtárban lévő Registry Edit (regedit.exe) már nem. Egy másik könytárban lévő számológép (C:\\Windows\System32\calc.exe) szintén indítható elérési út megadása nélkül. Erről a nehezen értelmezhető jelenségről nem találtam hivatalos dokumentációt.
A traceInstructions() metódus true értékkel való paraméterezésével (traceInstructions(true)) a JVM minden programutasítást olyan járulékos információval lát el, amely hatékonyan segít debugging üzemmódban, azaz kódhibák kereséseker (Programozási molytalanítás avagy a debug üzemmód című fejezet). A metódus false értékkel deaktiválható.
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
runtime.traceInstructions(true);
System.out.println("Aktivalva!");
}
}
Végeredmény:
Aktivalva!
A traceMethodCalls() metódus true értékkel való paraméterezésével (traceMethodCalls(true)) a JVM minden metódushívást olyan járulékos információval lát el, amely hatékonyan segít debugging üzemmódban, azaz kódhibák kereséseker (Programozási molytalanítás avagy a debug üzemmód című fejezet). A metódus false értékkel deaktiválható.
public class Main {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
runtime.traceMethodCalls(true);
System.out.println("Aktivalva!");
}
}
Végeredmény:
Aktivalva!
További érdekes és fontos metódus az addShutdownHook(), amelyet A többszálú programozás alapjai (multithread) című fejezetcsomag Néhány alapvető szálmetódus című fejezetében fogunk ismertetni és felhasználni.