Runtime源碼解析(JDK1.8)

package java.lang;

import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.StringTokenizer;

/**
 * Runtime類,裏面能夠得到應用運行時的一些狀態(主要包括使用的內存和cpu個數)和在應用運行時執行一些操做(程序退出、執行gc、設置退出時的鉤子函數)。
 * 用到了單例模式:確保一個類最多隻有一個實例,並提供一個全局訪問點。
 */
public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * 應用了設計模式中的單例模式餓漢式(線程安全)
     * 返回與當前應用程序相關的java運行時對象。
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }

    /**
     * 私有構造函數,單例模式的條件,返回與當前應用程序相關的java運行時對象,不支持new的Runtime
     */
    private Runtime() {
    }

    /**
     * 經過啓動虛擬機的關閉序列,終止當前正在運行的 Java 虛擬機。此方法從不正常返回。能夠將變量做爲一個狀態碼;根據慣例,非零的狀態碼錶示非正常終止。
     * 虛擬機的關閉序列包含兩個階段。在第一個階段中,會以某種未指定的順序啓動全部已註冊的關閉鉤子(hook)(若是有的話),而且容許它們同時運行直至結束。
     * 在第二個階段中,若是已啓用退出終結,則運行全部未調用的終結方法。一旦完成這個階段,虛擬機就會暫停。
     * 若是在虛擬機已開始其關閉序列後才調用此方法,那麼若正在運行關閉鉤子,則將無限期地阻斷此方法。
     * 若是已經運行完關閉鉤子,而且已啓用退出終結 (on-exitfinalization),那麼此方法將利用給定的狀態碼(若是狀態碼是非零值)暫停虛擬機;不然將無限期地阻斷虛擬機。
     */
    public void exit(int status) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExit(status);
        }
        Shutdown.exit(status);
    }

    /**
     * 註冊新的虛擬機來關閉鉤子。
     */
    public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        ApplicationShutdownHooks.add(hook);
    }

    /**
     * 取消註冊某個先前已註冊的虛擬機關閉鉤子。
     * 若是指定的鉤子先前已註冊而且成功地取消註冊,則返回 true,其餘狀況返回 false。
     */
    public boolean removeShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        return ApplicationShutdownHooks.remove(hook);
    }

    /**
     * 強行終止目前正在運行的 Java 虛擬機。此方法從不正常返回。
     * 應當心使用此方法。與 exit方法不一樣,此方法不會啓動關閉鉤子,而且若是已啓用退出終結,此方法也不會運行未調用的終結方法。
     * 若是已經發起關閉序列,那麼此方法不會等待全部正在運行的關閉鉤子或終結方法完成其工做。
     */
    public void halt(int status) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkExit(status);
        }
        Shutdown.halt(status);
    }

    /**
     * 在退出時啓用或禁用終結;這樣作可指定擁有未被自動調用終結方法的全部對象的終結方法,並將在退出 Java 運行時前運行此終結方法。默認狀況下,禁用退出終結。
     * 若是有安全管理器,則首先使用 0 做爲變量來調用其 checkExit 方法,以確保容許退出。這可能會致使 SecurityException。
     */
    @Deprecated
    public static void runFinalizersOnExit(boolean value) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            try {
                security.checkExit(0);
            } catch (SecurityException e) {
                throw new SecurityException("runFinalizersOnExit");
            }
        }
        Shutdown.setRunFinalizersOnExit(value);
    }

    /**
     * 在單獨的進程中執行指定的字符串命令。
     * 對於 exec(command) 形式的調用而言,其行爲與調用 exec(command, null, null) 徹底相同。
     */
    public Process exec(String command) throws IOException {
        return exec(command, null, null);
    }

    /**
     * 在指定環境的單獨進程中執行指定的字符串命令。
     * 對於 exec(command, envp) 形式的調用而言,其行爲與調用 exec(command, envp, null) 徹底相同。
     */
    public Process exec(String command, String[] envp) throws IOException {
        return exec(command, envp, null);
    }

    /**
     * 在有指定環境和工做目錄的獨立進程中執行指定的字符串命令。
     * 對於 exec(command, envp, dir) 形式的調用而言,其行爲與調用 exec(cmdarray, envp, dir) 徹底相同,其中 cmdarray 是 command 中全部標記的數組。
     * 更準確地說,可使用經過調用 new StringTokenizer(command) 建立的 StringTokenizer 將 command 字符串拆解成標記,調用時不對字符類別作進一步的修改。
     * 而後將標記生成器所生成的標記以相同的順序放入新的字符串數組 cmdarray 中。
     */
    public Process exec(String command, String[] envp, File dir)
            throws IOException {
        if (command.length() == 0)
            throw new IllegalArgumentException("Empty command");

        StringTokenizer st = new StringTokenizer(command);
        String[] cmdarray = new String[st.countTokens()];
        for (int i = 0; st.hasMoreTokens(); i++)
            cmdarray[i] = st.nextToken();
        return exec(cmdarray, envp, dir);
    }

    /**
     * 在單獨的進程中執行指定命令和變量。
     * 對於 exec(cmdarray) 形式的調用而言,其行爲與調用 exec(cmdarray, null, null) 徹底相同。
     */
    public Process exec(String cmdarray[]) throws IOException {
        return exec(cmdarray, null, null);
    }

    /**
     * 在指定環境的獨立進程中執行指定命令和變量。
     * 對於 exec(cmdarray, envp) 形式的調用而言,其行爲與調用 exec(cmdarray, envp, null) 徹底相同。
     */
    public Process exec(String[] cmdarray, String[] envp) throws IOException {
        return exec(cmdarray, envp, null);
    }


    /**
     * 在指定環境和工做目錄的獨立進程中執行指定的命令和變量。
     * 給定的字符串數組 cmdarray 表示一個命令行標記,字符串數組 envp 則表示「環境」變量設置,此方法會建立一個新進程,而指定的命令就在這個進程中執行。
     * 此方法檢查 cmdarray 是不是一條有效的操做系統命令。哪些命令有效取決於系統,可是該命令至少必須有一個非 null 字符串的非空列表。
     */
    public Process exec(String[] cmdarray, String[] envp, File dir)
            throws IOException {
        return new ProcessBuilder(cmdarray)
                .environment(envp)
                .directory(dir)
                .start();
    }

    /**
     * 向 Java 虛擬機返回可用處理器的數目。
     * 該值在特定的虛擬機調用期間可能發生更改。所以,對可用處理器數目很敏感的應用程序應該不按期地輪詢該屬性,並相應地調整其資源用法。
     * 虛擬機可用的最大處理器數目;從不小於 1
     */
    public native int availableProcessors();

    /**
     * 返回 Java 虛擬機中的空閒內存量。調用 gc 方法可能致使 freeMemory 返回值的增長。
     */
    public native long freeMemory();

    /**
     * 返回 Java 虛擬機中的內存總量。此方法返回的值可能隨時間的推移而變化,這取決於主機環境。
     */
    public native long totalMemory();

    /**
     * 返回 Java 虛擬機試圖使用的最大內存量。若是內存自己沒有限制,則返回值 Long.MAX_VALUE。
     */
    public native long maxMemory();

    /**
     * 運行垃圾回收器。調用此方法意味着 Java 虛擬機作了一些努力來回收未用對象,以便可以快速地重用這些對象當前佔用的內存。
     * 當控制從方法調用中返回時,虛擬機已經盡最大努力回收了全部丟棄的對象。
     * 垃圾回收機制主要有兩類:引用計數收集器  跟蹤收集器
     */
    public native void gc();

    /* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
    private static native void runFinalization0();

    /**
     * 運行掛起 finalization 的全部對象的終止方法。
     * 調用此方法意味着 Java 虛擬機作了一些努力運行已被丟棄對象的 finalize 方法,
     * 可是這些對象的 finalize 方法尚未運行。當控制從方法調用中返回時,Java 虛擬機已經盡最大努力去完成全部未執行的終止方法。
     * 若是不顯式調用 runFinalization 方法,則 Java 虛擬機會根據須要在單獨的線程中自動執行此終止過程。
     */
    public void runFinalization() {
        runFinalization0();
    }

    /**
     * 啓用/禁用指令跟蹤。
     */
    public native void traceInstructions(boolean on);

    /**
     * 啓用/禁用方法調用跟蹤。
     */
    public native void traceMethodCalls(boolean on);

    /**
     * 加載具備指定動態庫。
     */
    @CallerSensitive
    public void load(String filename) {
        load0(Reflection.getCallerClass(), filename);
    }

    synchronized void load0(Class<?> fromClass, String filename) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkLink(filename);
        }
        if (!(new File(filename).isAbsolute())) {
            throw new UnsatisfiedLinkError(
                    "Expecting an absolute path of the library: " + filename);
        }
        ClassLoader.loadLibrary(fromClass, filename, true);
    }

    /**
     * 加載具備指定動態庫。
     */
    @CallerSensitive
    public void loadLibrary(String libname) {
        loadLibrary0(Reflection.getCallerClass(), libname);
    }

    synchronized void loadLibrary0(Class<?> fromClass, String libname) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkLink(libname);
        }
        if (libname.indexOf((int) File.separatorChar) != -1) {
            throw new UnsatisfiedLinkError(
                    "Directory separator should not appear in library name: " + libname);
        }
        ClassLoader.loadLibrary(fromClass, libname, false);
    }

    /**
     * 建立輸入流的本地化版本。此方法獲取 InputStream,並返回除本地化外其餘全部方面都和變量等效的 InputStream,這些方面包括:做爲本地字符集中的字符從流中被讀取,並將它們從本地字符集自動轉換爲 Unicode。
     */
    @Deprecated
    public InputStream getLocalizedInputStream(InputStream in) {
        return in;
    }

    /**
     * 建立輸出流的本地化版本。此方法獲取 OutputStream,並返回除本地化外其餘全部方面都和變量等效的 OutputStream,這些方面包括:做爲 Unicode 字符被寫入流中,並被自動轉換爲本地字符集。
     * 若是參數已是本地流,則可做爲結果返回。
     */
    @Deprecated
    public OutputStream getLocalizedOutputStream(OutputStream out) {
        return out;
    }

}
相關文章
相關標籤/搜索