0
点赞
收藏
分享

微信扫一扫

09 java.lang.Runtime


Runtime

2015.01.19
                                                            By 970655147

这个类主要适用于添加jvm关闭时的钩子函数, 运行进程[使用ProcessBuilder], 获取jvm可使用的cpu个数, 内存的使用情况, 运行gc, 关闭jvm, 加载本地库等等

start ->

声明

, 大家可以看看注释

/**
 * Every Java application has a single instance of class
 * <code>Runtime</code> that allows the application to interface with
 * the environment in which the application is running. The current
 * runtime can be obtained from the <code>getRuntime</code> method.
 * <p>
 * An application cannot create its own instance of this class.
 *
 * @author  unascribed
 * @see     java.lang.Runtime#getRuntime()
 * @since   JDK1.0
 */

public class Runtime

Runtime. 属性

// 可以通过getRuntime获取runtime
    private static Runtime currentRuntime = new Runtime();

Runtime. Runtime()

// 构造方法私有化 构造单例
    /** Don't let anyone else instantiate this class */
    private Runtime() {}

Runtime. getRuntime()

// 获取Runtime
    public static Runtime getRuntime() {
        return currentRuntime;
    }

Runtime. exit(int status)

// System.ext(exitCode ) 也是调用了Runtime.exit(exitCode )
public void exit(int status) {
    // security check
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExit(status);
        }
        // exit
        Shutdown.exit(status);
    }

Shutdown. exit(int status)
    /* Invoked by Runtime.exit, which does all the security checks.
     * Also invoked by handlers for system-provided termination events,
     * which should pass a nonzero status code.
     */
static void exit(int status) {
    // 如果status不为0, 更新runFinalizersOnExit为false
    // 检测状态, 如果state为RUNNING, 更新state为HOOKS
        // 如果状态为FINALIZERS[sequences方法中得到该状态], 则判断status如果其不为0, 直接中断jvm
            // 否则 设置需要运行所有未调用的终结方法。
    // 如果状态为FINALIZERS 并且status为0, 则运行所有未调用的终结方法 并中断jvm
    // 如果状态为RUNNING 或者HOOKS, 先运行所有的关闭虚拟机的钩子函数, 然后如果runFinalizersOnExit为true [Shutdown. setRunFinalizersOnExit(boolean)] 的话, 运行所有未调用的终结方法 并中断jvm
        boolean runMoreFinalizers = false;
        synchronized (lock) {
            if (status != 0) runFinalizersOnExit = false;
            switch (state) {
            case RUNNING:       /* Initiate shutdown */
                state = HOOKS;
                break;
            case HOOKS:         /* Stall and halt */
                break;
            case FINALIZERS:
                if (status != 0) {
                    /* Halt immediately on nonzero status */
                    halt(status);
                } else {
                    /* Compatibility with old behavior:
                     * Run more finalizers and then halt
                     */
                    runMoreFinalizers = runFinalizersOnExit;
                }
                break;
            }
        }
        if (runMoreFinalizers) {
            runAllFinalizers();
            halt(status);
        }
        synchronized (Shutdown.class) {
            /* Synchronize on the class object, causing any other thread
             * that attempts to initiate shutdown to stall indefinitely
             */
            sequence();
            halt(status);
        }
    }

Shutdown. halt (int status)
    /* The halt method is synchronized on the halt lock
     * to avoid corruption of the delete-on-shutdown file list.
     * It invokes the true native halt method.
     */
    static void halt(int status) {
        synchronized (haltLock) {
            halt0(status);
        }
    }

Shutdown. halt0 (int status)
    static native void halt0(int status);

Shutdown. runAllFinalizers ( )
    /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
    private static native void runAllFinalizers();

Shutdown. sequence()
    /* The actual shutdown sequence is defined here.
     *
     * If it weren't for runFinalizersOnExit, this would be simple -- we'd just
     * run the hooks and then halt.  Instead we need to keep track of whether
     * we're running hooks or finalizers.  In the latter case a finalizer could
     * invoke exit(1) to cause immediate termination, while in the former case
     * any further invocations of exit(n), for any n, simply stall.  Note that
     * if on-exit finalizers are enabled they're run iff the shutdown is
     * initiated by an exit(0); they're never run on exit(n) for n != 0 or in
     * response to SIGINT, SIGTERM, etc.
     */
private static void sequence() {
// 确保状态为HOOKS, [必需保证是从exit方法 或者shutdown方法调用]
// 先运行所有的关闭虚拟机的钩子函数, 并更新state为FINALIZERS
// 如果runFinalizersOnExit为true [Shutdown. setRunFinalizersOnExit(boolean)] 的话, 运行所有未调用的终结方法 并中断jvm
// 这里我们先到这里, 待会儿再来详细分析Shutdown.java
        synchronized (lock) {
            /* Guard against the possibility of a daemon thread invoking exit
             * after DestroyJavaVM initiates the shutdown sequence
             */
            if (state != HOOKS) return;
        }
        runHooks();
        boolean rfoe;
        synchronized (lock) {
            state = FINALIZERS;
            rfoe = runFinalizersOnExit;
        }
        if (rfoe) runAllFinalizers();
    }

Runtime. addShutdownHook(Thread hook)

public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        // 添加hook[Callback]方法
        ApplicationShutdownHooks.add(hook);
    }

ApplicationShutdownHooks. add(Thread hook)
    static synchronized void add(Thread hook) {
        if(hooks == null)
            throw new IllegalStateException("Shutdown in progress");

        if (hook.isAlive())
            throw new IllegalArgumentException("Hook already running");

        if (hooks.containsKey(hook))
            throw new IllegalArgumentException("Hook previously registered");

        hooks.put(hook, hook);
    }

/* The set of registered hooks */
    private static IdentityHashMap<Thread, Thread> hooks;

那么ApplicationShutdown又是怎么和Shutdown关联起来的呢?, 请看下面

ApplicationShutdown. staticBlock

static {
        try {
        // 其实就是为Shutdown在slot[1]处添加了一个钩子, 来运行applicationShutdown收集的所有shutdownHooks
// 这里我们先到这里, 待会儿再来详细分析ApplicationShutdown.java
            Shutdown.add(1 /* shutdown hook invocation order */,
                false /* not registered if shutdown in progress */,
                new Runnable() {
                    public void run() {
                        runHooks();
                    }
                }
            );
            hooks = new IdentityHashMap<>();
        } catch (IllegalStateException e) {
            // application shutdown hooks cannot be added if
            // shutdown is in progress.
            hooks = null;
        }
    }

Runtime. remove(Thread hook)

static synchronized boolean remove(Thread hook) {
        if(hooks == null)
            throw new IllegalStateException("Shutdown in progress");

        if (hook == null)
            throw new NullPointerException();
        // 移除hook方法
        return hooks.remove(hook) != null;
    }

Runtime. halt(int status)

public void halt(int status) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkExit(status);
        }
        // 中断
        Shutdown.halt(status);
    }

Runtime. runFinalizersOnExit(boolean value)

@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");
            }
        }
        // 在exit之前是否运行finalizer
        // 设置Shutdown. runFinalizersOnExit, 但是由于不安全, 以过时
        Shutdown.setRunFinalizersOnExit(value);
    }

Runtime. exec(String command)

public Process exec(String command) throws IOException {
        return exec(command, null, null);
    }


Runtime. exec(String command, String[] envp) throws IOException
    public Process exec(String command, String[] envp) throws IOException {
        return exec(command, envp, null);
    }


Runtime. exec(String command, String[] envp, File dir) throws IOException
    public Process exec(String command, String[] envp, File dir)
        throws IOException {
        if (command.length() == 0)
            throw new IllegalArgumentException("Empty command");
        // 将command构建成command数组 之后利用ProcessBuilder.start
        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);
    }


Runtime exec(String[] cmdarray, String[] envp, File dir) throws IOException
    public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        // 利用ProcessBuilder创建一个进程
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }

Runtime.availableProcessors()[native]

public native int availableProcessors();

Runtime.freeMemory()[native]

public native long freeMemory();

Runtime.totalMemory()[native]

public native long totalMemory();

Runtime.maxMemory()[native]

public native long maxMemory();

Runtime.gc()[native]

// System.gc() 就是调用的这个gc方法
    public native void gc();

Runtime. runFinalization()

public void runFinalization() {
        runFinalization0();
    }

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

Runtime. traceInstructions(boolean on)[native]

public native void traceInstructions(boolean on);

Runtime. traceMethodCalls(boolean on)

public native void traceMethodCalls(boolean on);

Runtime.load(String filename)

@CallerSensitive
    public void load(String filename) {
        load0(Reflection.getCallerClass(), filename);
    }

Runtime. load0(Class fromClass, String 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);
        }
        // ..类加载器加载指定的dynamic library  第三个参数应该是是否是绝对路径吧 看不懂..
        ClassLoader.loadLibrary(fromClass, filename, true);
    }

Runtime. loadLibrary(String libname)

@CallerSensitive
    public void loadLibrary(String libname) {
        loadLibrary0(Reflection.getCallerClass(), libname);
    }

Runtime. loadLibrary0(Class fromClass, String 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);
        }
        // 类加载器加载指定的dynamic library
        ClassLoader.loadLibrary(fromClass, libname, false);
    }


ClassLoader. loadLibrary(Class fromClass, String name, boolean isAbsolute)
    // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
    static void loadLibrary(Class fromClass, String name,
                            boolean isAbsolute) {
        ClassLoader loader =
            (fromClass == null) ? null : fromClass.getClassLoader();
        // 初始化系统环境变量
        if (sys_paths == null) {
            usr_paths = initializePath("java.library.path");
            sys_paths = initializePath("sun.boot.library.path");
        }
        // 如果用户给定的是绝对路径 直接加载
        if (isAbsolute) {
            if (loadLibrary0(fromClass, new File(name))) {
                return;
            }
            throw new UnsatisfiedLinkError("Can't load library: " + name);
        }
        // 在当前目录寻找指定library
        if (loader != null) {
            String libfilename = loader.findLibrary(name);
            if (libfilename != null) {
                File libfile = new File(libfilename);
                if (!libfile.isAbsolute()) {
                    throw new UnsatisfiedLinkError(
    "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
                }
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
                throw new UnsatisfiedLinkError("Can't load " + libfilename);
            }
        }
        // 在系统环境变量所在路径查找指定library
        for (int i = 0 ; i < sys_paths.length ; i++) {
            File libfile = new File(sys_paths[i], System.mapLibraryName(name));
            if (loadLibrary0(fromClass, libfile)) {
                return;
            }
        }
        // 在用户环境变量所在路径查找指定library
        if (loader != null) {
            for (int i = 0 ; i < usr_paths.length ; i++) {
                File libfile = new File(usr_paths[i],
                                        System.mapLibraryName(name));
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
            }
        }
        // 没找到指定的library
        // Oops, it failed
        throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
    }

Runtime. getLocalizedInputStream(InputStream in)

@Deprecated
    public InputStream getLocalizedInputStream(InputStream in) {
        return in;
    }

Runtime. getLocalizedOutputStream(OutputStream out)

@Deprecated
    public OutputStream getLocalizedOutputStream(OutputStream out) {
        return out;
    }

ApplicationShutdownHooks [class]

class ApplicationShutdownHooks {
    /* The set of registered hooks */
private static IdentityHashMap<Thread, Thread> hooks;
        // 其实就是为Shutdown在slot[1]处添加了一个钩子, 来运行applicationShutdown收集的所有shutdownHooks
        // 整个类实际上就是为Shutdown.java 服务的, 将Runtime.addShutdownHook(Thread), removeShutdownHook(Thread), 注册的所有钩子, 作为Shutdown的1号钩子
    static {
        try {
            Shutdown.add(1 /* shutdown hook invocation order */,
                false /* not registered if shutdown in progress */,
                new Runnable() {
                    public void run() {
                        runHooks();
                    }
                }
            );
            hooks = new IdentityHashMap<>();
        } catch (IllegalStateException e) {
            // application shutdown hooks cannot be added if
            // shutdown is in progress.
            hooks = null;
        }
    }

    // 初始化构造方法, 不存在实例
    private ApplicationShutdownHooks() {}

    /* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
     * but does not do any security checks.
     */
    // 添加一个关闭虚拟机 时需要执行钩子函数
    static synchronized void add(Thread hook) {
        if(hooks == null)
            throw new IllegalStateException("Shutdown in progress");

        if (hook.isAlive())
            throw new IllegalArgumentException("Hook already running");

        if (hooks.containsKey(hook))
            throw new IllegalArgumentException("Hook previously registered");

        hooks.put(hook, hook);
    }

    /* Remove a previously-registered hook.  Like the add method, this method
     * does not do any security checks.
     */
    // 移除一个关闭虚拟机 时需要执行钩子函数
    static synchronized boolean remove(Thread hook) {
        if(hooks == null)
            throw new IllegalStateException("Shutdown in progress");

        if (hook == null)
            throw new NullPointerException();

        return hooks.remove(hook) != null;
    }

    /* Iterates over all application hooks creating a new thread for each
     * to run in. Hooks are run concurrently and this method waits for
     * them to finish.
     */
    // 依次执行每一个钩子函数, 并等待所有的钩子函数对应的线程执行完毕
    static void runHooks() {
        Collection<Thread> threads;
        synchronized(ApplicationShutdownHooks.class) {
            threads = hooks.keySet();
            hooks = null;
        }

        for (Thread hook : threads) {
            hook.start();
        }
        for (Thread hook : threads) {
            try {
                hook.join();
            } catch (InterruptedException x) { }
        }
    }
}

Shutdown [class]

class Shutdown {

/* Shutdown state */
// 三种状态, 初始化当前的状态为RUNNING
// 是否需要在虚拟机关闭的时候, 运行所有未调用的终结方法
// 最大的系统钩子的个数, 以及所有的钩子
    private static final int RUNNING = 0;
    private static final int HOOKS = 1;
    private static final int FINALIZERS = 2;
    private static int state = RUNNING;

    /* Should we run all finalizers upon exit? */
    private static boolean runFinalizersOnExit = false;

    // The system shutdown hooks are registered with a predefined slot.
    // The list of shutdown hooks is as follows:
    // (0) Console restore hook
    // (1) Application hooks
    // (2) DeleteOnExit hook
    private static final int MAX_SYSTEM_HOOKS = 10;
    private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];

// the index of the currently running shutdown hook to the hooks array
// 当前正在运行的钩子的索引
// 用于线程安全维护的锁, 用于中断处理的锁
    private static int currentRunningHook = 0;

    /* The preceding static fields are protected by this lock */
    private static class Lock { };
    private static Object lock = new Lock();

    /* Lock object for the native halt method */
    private static Object haltLock = new Lock();

/* Invoked by Runtime.runFinalizersOnExit */
    // 设置 是否jvm关闭的时候运行所有未调用的终结方法
    static void setRunFinalizersOnExit(boolean run) {
        synchronized (lock) {
            runFinalizersOnExit = run;
        }
    }

    /**
     * Add a new shutdown hook.  Checks the shutdown state and the hook itself,
     * but does not do any security checks.
     *
     * The registerShutdownInProgress parameter should be false except
     * registering the DeleteOnExitHook since the first file may
     * be added to the delete on exit list by the application shutdown
     * hooks.
     *
     * @params slot  the slot in the shutdown hook array, whose element
     *               will be invoked in order during shutdown
     * @params registerShutdownInProgress true to allow the hook
     *               to be registered even if the shutdown is in progress.
     * @params hook  the hook to be registered
     *
     * @throw IllegalStateException
     *        if registerShutdownInProgress is false and shutdown is in progress; or
     *        if registerShutdownInProgress is true and the shutdown process
     *           already passes the given slot
     */
static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
    //做一些校验, 添加一个系统钩子
        synchronized (lock) {
            if (hooks[slot] != null)
                throw new InternalError("Shutdown hook at slot " + slot + " already registered");

            if (!registerShutdownInProgress) {
                if (state > RUNNING)
                    throw new IllegalStateException("Shutdown in progress");
            } else {
                if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook))
                    throw new IllegalStateException("Shutdown in progress");
            }

            hooks[slot] = hook;
        }
    }

    /* Run all registered shutdown hooks
     */
private static void runHooks() {
    // 执行所有的钩子函数, 单线程执行
        for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
            try {
                Runnable hook;
                synchronized (lock) {
                    // acquire the lock to make sure the hook registered during
                    // shutdown is visible here.
                    currentRunningHook = i;
                    hook = hooks[i];
                }
                if (hook != null) hook.run();
            } catch(Throwable t) {
                if (t instanceof ThreadDeath) {
                    ThreadDeath td = (ThreadDeath)t;
                    throw td;
                }
            }
        }
    }

    /* The halt method is synchronized on the halt lock
     * to avoid corruption of the delete-on-shutdown file list.
     * It invokes the true native halt method.
     */
static void halt(int status) {
    // 中断jvm虚拟机
        synchronized (haltLock) {
            halt0(status);
        }
    }

    // 中断jvm
    static native void halt0(int status);

/* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
// jvm关闭的时候运行所有未调用的终结方法
    private static native void runAllFinalizers();


    /* The actual shutdown sequence is defined here.
     *
     * If it weren't for runFinalizersOnExit, this would be simple -- we'd just
     * run the hooks and then halt.  Instead we need to keep track of whether
     * we're running hooks or finalizers.  In the latter case a finalizer could
     * invoke exit(1) to cause immediate termination, while in the former case
     * any further invocations of exit(n), for any n, simply stall.  Note that
     * if on-exit finalizers are enabled they're run iff the shutdown is
     * initiated by an exit(0); they're never run on exit(n) for n != 0 or in
     * response to SIGINT, SIGTERM, etc.
     */
private static void sequence() {
    // 确保状态为HOOKS, [必需保证是从exit方法 或者shutdown方法调用]
// 先运行所有的关闭虚拟机的钩子函数, 并更新state为FINALIZERS
// 如果runFinalizersOnExit为true [Shutdown. setRunFinalizersOnExit(boolean)] 的话, 运行所有未调用的终结方法 并中断jvm
        synchronized (lock) {
            /* Guard against the possibility of a daemon thread invoking exit
             * after DestroyJavaVM initiates the shutdown sequence
             */
            if (state != HOOKS) return;
        }
        runHooks();
        boolean rfoe;
        synchronized (lock) {
            state = FINALIZERS;
            rfoe = runFinalizersOnExit;
        }
        if (rfoe) runAllFinalizers();
    }


    /* Invoked by Runtime.exit, which does all the security checks.
     * Also invoked by handlers for system-provided termination events,
     * which should pass a nonzero status code.
     */
static void exit(int status) {
    // 如果status不为0, 更新runFinalizersOnExit为false
    // 检测状态, 如果state为RUNNING, 更新state为HOOKS
        // 如果状态为FINALIZERS[sequences方法中得到该状态], 则判断status如果其不为0, 直接中断jvm
            // 否则 设置需要运行所有未调用的终结方法。
    // 如果状态为FINALIZERS 并且status为0, 则运行所有未调用的终结方法 并中断jvm
    // 如果状态为RUNNING 或者HOOKS, 先运行所有的关闭虚拟机的钩子函数, 然后如果runFinalizersOnExit为true [Shutdown. setRunFinalizersOnExit(boolean)] 的话, 运行所有未调用的终结方法 并中断jvm
        boolean runMoreFinalizers = false;
        synchronized (lock) {
            if (status != 0) runFinalizersOnExit = false;
            switch (state) {
            case RUNNING:       /* Initiate shutdown */
                state = HOOKS;
                break;
            case HOOKS:         /* Stall and halt */
                break;
            case FINALIZERS:
                if (status != 0) {
                    /* Halt immediately on nonzero status */
                    halt(status);
                } else {
                    /* Compatibility with old behavior:
                     * Run more finalizers and then halt
                     */
                    runMoreFinalizers = runFinalizersOnExit;
                }
                break;
            }
        }
        if (runMoreFinalizers) {
            runAllFinalizers();
            halt(status);
        }
        synchronized (Shutdown.class) {
            /* Synchronize on the class object, causing any other thread
             * that attempts to initiate shutdown to stall indefinitely
             */
            sequence();
            halt(status);
        }
    }


    /* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon
     * thread has finished.  Unlike the exit method, this method does not
     * actually halt the VM.
     */
static void shutdown() {
    // 检测状态, 如果state为RUNNING, 更新state为HOOKS
    // 先运行所有的关闭虚拟机的钩子函数, 然后如果runFinalizersOnExit为true [Shutdown. setRunFinalizersOnExit(boolean)] 的话, 运行所有未调用的终结方法 并中断jvm
    // 这里与上面的exit方法的区别存在两处, 一处在于对于FINALIZERS状态的处理, 另一处在于, 这里不会中断jvm虚拟机
        synchronized (lock) {
            switch (state) {
            case RUNNING:       /* Initiate shutdown */
                state = HOOKS;
                break;
            case HOOKS:         /* Stall and then return */
            case FINALIZERS:
                break;
            }
        }
        synchronized (Shutdown.class) {
            sequence();
        }
    }

}

附上Shutdown状态切换图 :

09 java.lang.Runtime_java-源码

->

ok, Runtime 到此结束了, 这个类主要涉及其他的两个ApplicationShutdown.java, 和Shutdown.java 两个包级别的类

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!


举报

相关推荐

0 条评论