簡介
開發者有時候會在什麼東西應該在編譯的時候載入進來以及什麼東西該在運行的時候使用之間做出抉擇,前者有時候被稱為編譯時期。
一段時間以來,技術類作者都拒絕使用"運行時刻"作為一種術語,他們堅持類似於"一個程式在運行"之類的說法,用以避免需要一個專門的術語。後來,這個術語逐漸地蔓延到通常的套用中。
相關內容
Runtime類封裝了運行時的環境。每個Java應用程式都有一個Runtime 類實例,使應用程式能夠與其運行的環境相連線。
一般不能實例化一個Runtime對象,應用程式也不能創建自己的Runtime 類實例,但可以通過getRuntime 方法獲取當前Runtime運行時對象的引用。
一旦得到了一個當前的Runtime對象的引用,就可以調用Runtime對象的方法去控制Java虛擬機的狀態和行為。
當Applet和其他不被信任的代碼調用任何Runtime方法時,常常會引起SecurityException異常。
常見套用
1、記憶體管理:
Java提供了無用單元自動收集機制。通過totalMemory()和freeMemory()方法可以知道對象的堆記憶體有多大,還剩多少。
Java會周期性的回收垃圾對象(未使用的對象),以便釋放記憶體空間。但是如果想先於收集器的下一次指定周期來收集廢棄的對象,可以通過調用gc()方法來根據需要運行無用單元收集器。一個很好的試驗方法是先調用gc()方法,然後調用freeMemory()方法來查看基本的記憶體使用情況,接著執行代碼,然後再次調用freeMemory()方法看看分配了多少記憶體。下面的程式演示了這個構想。
class MemoryDemo{
public static void main(String args[]){
Runtime r = Runtime.getRuntime();
long mem1,mem2;
Integer someints[] = new Integer[1000];
System.out.println("Total memory is :" + r.totalMemory());
mem1 = r.freeMemory();
System.out.println("Initial free is : " + mem1);
r.gc();
mem1 = r.freeMemory();
System.out.println("Free memory after garbage collection : " + mem1);
//allocate integers
for(int i=0; i<1000; i++) someints[i] = new Integer(i);
mem2 = r.freeMemory();
System.out.println("Free memory after allocation : " + mem2);
System.out.println("Memory used by allocation : " +(mem1-mem2));
//discard Intergers
for(int i=0; i<1000; i++) someints = null;
r.gc(); //request garbage collection
mem2 = r.freeMemory();
System.out.println("Free memory after collecting " + "discarded integers : " + mem2);
}
}
編譯後運行結果如下(不同的機器不同時間運行的結果也不一定一樣):
Total memory is :2031616
Initial free is : 1818488
Free memory after garbage collection : 1888808
Free memory after allocation : 1872224
Memory used by allocation : 16584
Free memory after collecting discarded integers : 1888808
2、執行其他程式
在安全的環境中,可以在多任務作業系統中使用Java去執行其他特別大的進程(也就是程式)。exec()方法有幾種形式命名想要運行的程式和它的輸入參數。exec()方法返回一個Process對象,可以使用這個對象控制Java程式與新運行的進程進行互動。exec()方法本質是依賴於環境。
下面的例子是使用exec()方法啟動windows的記事本notepad。這個例子必須在Windows作業系統上運行。
class ExecDemo {
public static void main(String args[]){
Runtime r = Runtime.getRuntime();
Process p = null;
try{
p = r.exec("notepad");
} catch (Exception e) {
System.out.println("Error executing notepad.");
}
}
}
exec()還有其他幾種形式,例子中演示的是最常用的一種。exec()方法返回Process對象後,在新程式開始運行後就可以使用Process的方法了。可以用destory()方法殺死子進程,也可以使用waitFor()方法等待程式直到子程式結束,exitValue()方法返回子進程結束時返回的值。如果沒有錯誤,將返回0,否則返回非0。下面是關於exec()方法的例子的改進版本。例子被修改為等待,直到運行的進程退出:
class ExecDemoFini {
public static void main(String args[]){
Runtime r = Runtime.getRuntime();
Process p = null;
try{
p = r.exec("notepad");
p.waitFor();
} catch (Exception e) {
System.out.println("Error executing notepad.");
}
System.out.println("Notepad returned " + p.exitValue());
}
}
下面是運行的結果(當關閉記事本後,會接著運行程式,列印信息):
Notepad returned 0
按任意鍵繼續. . .
當子進程正在運行時,可以對標準輸入輸出進行讀寫。getOutputStream()方法和getInPutStream()方法返回對子進程的標準輸入和輸出。
系統
Run-time system
一個run-time system也叫做運行時系統,運行時環境,實現了一個計算機語言的核心行為。
每一種計算機語言都實現了某種形式的運行時系統,無論這種語言是編譯語言,解釋語言,還是嵌入式領域特定語言。【compiled language, interpreted language, embedded domain-specific language】或者有些語言會通過API調用以執行緒形式調用。除了要支持語言的低級行為之外,一個運行時系統還要實現更高層次的行為,甚至要執行類型檢查,調試,或者代碼生成與最佳化。
作為一個簡單的運行時系統的例子,C語言的運行時系統是編譯器插入到執行檔中的一個特殊的指令集合。此外,這些特殊的指令集合還管理處理器棧,為局部變數分配空間,並把函式調用參數拷貝到棧頂。之所以這些行為是運行時系統的一部分而不是語言的關鍵部分,是因為這些行為時系統行為,這些行為在程式的執行全過程中維護了棧的狀態。並且這些系統行為實現了語言的執行模型,而不是實現了與特定計算結果有關的語義。
另一個展示運行時系統特性的例子是使用API與運行時系統互動。對這個API的調用看起來就像是對軟體庫的調用一樣,然而運行時系統添加了實現了一個執行模型的系統性行為。這裡的API添加了插樁代碼會調用運行時系統,而不是使用一個包含代碼的庫直接實現軟體行為。一個人只要了解構成一個庫的語言就能夠理解這個庫的行為。然而,一個人要想了解剛才那個調用運行時庫的API不能只了解構成API的語言本身。還要知道由運行時系統實現的執行模型是什麼樣的。
這就是一種嵌入式語言如posix threads和一個軟體庫的區別。雖然posix threads和軟體庫都是通過一個API調用,但是posix threads的行為不能通過代碼用的語言本身理解。實際上posix threads的調用還是要依賴於運行時系統提供的執行模型。
某些compiled或者interpreted的語言提供一個允許套用代碼直接和運行時系統互動的接口。一個例子是JAVA中的Thread類,通常情況下一個語言的核心行為(如任務調度和資源管理)是不能夠通過這種方式使得套用代碼能夠接觸到的。
其他
API預覽
addShutdownHook(Thread hook)
註冊新的虛擬機來關閉掛鈎。
availableProcessors()
向 Java虛擬機返回可用處理器的數目。
exec(String command)
在單獨的進程中執行指定的字元串命令。
exec(String[] cmdarray)
在單獨的進程中執行指定命令和變數。
exec(String[] cmdarray, String[] envp)
在指定環境的獨立進程中執行指定命令和變數。
exec(String[] cmdarray, String[] envp, File dir)
在指定環境和工作目錄的獨立進程中執行指定的命令和變數。
exec(String command, String[] envp)
在指定環境的單獨進程中執行指定的字元串命令。
exec(String command, String[] envp, File dir)
在有指定環境和工作目錄的獨立進程中執行指定的字元串命令。
exit(int status)
通過啟動虛擬機的關閉序列,終止當前正在運行的 Java虛擬機。
freeMemory()
返回 Java虛擬機中的空閒記憶體量。
gc()
運行垃圾回收器。
InputStream getLocalizedInputStream(InputStream in)
已過時。 從 JDK 1.1 開始,將本地編碼位元組流轉換為 Unicode字元流的首選方法是使用 InputStreamReader 和 BufferedReader 類。
OutputStream getLocalizedOutputStream(OutputStream out)
已過時。 從 JDK 1.1 開始,將 Unicode字元流轉換為本地編碼位元組流的首選方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 類。
getRuntime()
返回與當前 Java應用程式相關的運行時對象。
halt(int status)
強行終止目前正在運行的 Java 虛擬機。
load(String filename)
載入作為動態庫的指定檔案名稱。
loadLibrary(String libname)
載入具有指定庫名的動態庫。
maxMemory()
返回 Java虛擬機試圖使用的最大記憶體量。
removeShutdownHook(Thread hook)
取消註冊某個先前已註冊的虛擬機關閉掛鈎。
runFinalization()
運行掛起 finalization 的所有對象的終止方法。
runFinalizersOnExit(value)
已過時。 此方法本身具有不安全性。它可能對正在使用的對象調用終結方法,而其他執行緒正在操作這些對象,從而導致不正確的行為或死鎖。
totalMemory()
返回 Java虛擬機中的記憶體總量。
traceInstructions(on)
啟用/禁用指令跟蹤。
traceMethodCalls(on)
啟用/禁用方法調用跟蹤。