1 Star 0 Fork 165

ElonChung / Java-Review

forked from flatfish / Java-Review 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Java-常用类-Runtime.md 13.01 KB
一键复制 编辑 原始数据 按行查看 历史
icanci 提交于 2020-09-07 23:09 . :fire:更新文件夹

Java - 常用类 - Runtime

从源码开始分析

public class Runtime {
    // 单例设置模式  懒汉式
    private static Runtime currentRuntime = new Runtime();

    public static Runtime getRuntime() {
        return currentRuntime;
    }

    private Runtime() {}

    // 从System获得系统安全管理器
    public void exit(int status) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExit(status);
        }
        // 执行Shutdown的静态方法 status是延迟时间
        Shutdown.exit(status);
    }

    //  调用 ApplicationShutdownHooks 的钩子方法 注册新的虚拟机关闭挂钩
    public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        ApplicationShutdownHooks.add(hook);
    }

    // 取消注册某个先前已注册的虚拟机关闭挂钩
    public boolean removeShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        return ApplicationShutdownHooks.remove(hook);
    }

    // 调用 Shutdown的halt 方法
    // 强行终止目前正在运行的Java虚拟机。 此方法从不正常返回
    public void halt(int status) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkExit(status);
        }
        Shutdown.halt(status);
    }

    // 启用或禁用退出终结
    @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);
    }

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

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

    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);
    }

    public Process exec(String cmdarray[]) throws IOException {
        return exec(cmdarray, null, null);
    }

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

    public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }

    // 本地方法 返回提供给Java虚拟机的处理器数量 也就是核心数量
    public native int availableProcessors();

    // 返回的空闲内存在Java虚拟机的数量。 调用gc方法可能会导致增加返回的值freeMemory.
    public native long freeMemory();

    // 返回的总共的内存在Java虚拟机的数量。
    public native long totalMemory();

    // 返回最大的内存
    public native long maxMemory();

    // 主动GC 但是不一定执行
    public native void gc();

    private static native void runFinalization0();

    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);

    }

    // 加载由指定的本地库libname说法。 
    // 该libname参数必须不包含任何特定于平台的前缀,文件扩展名或路径
    // 如果所谓的本地库libname静态与虚拟机相连,则JNI_OnLoad_ libname由库导出函数被调用
    @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);
    }

    // 获取本地的输入流 已经被弃用
    @Deprecated
    public InputStream getLocalizedInputStream(InputStream in) {
        return in;
    }
    
    // 获取输出流 已经被启用 
    @Deprecated
    public OutputStream getLocalizedOutputStream(OutputStream out) {
        return out;
    }
}

在Runtime的源码中还调用了 Shutdown类

我们来看一下源码

class Shutdown {

    // 终止得状态码
    // 正在运行
    private static final int RUNNING = 0;
    // 处于挂钩态
    private static final int HOOKS = 1;
    private static final int FINALIZERS = 2;
    // 默认就是 运行态
    private static int state = RUNNING;

    // 应该在退出时运行所有终结器 默认为false
    private static boolean runFinalizersOnExit = false;

    //系统关闭挂钩已在预定义的插槽中注册
    // 最大得 钩子数量
    private static final int MAX_SYSTEM_HOOKS = 10;
    // 挂钩线程数组
    private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];

    // 当前正在运行的关闭挂钩的索引钩阵列
    private static int currentRunningHook = 0;

    // 前面的静态字段受此锁保护
    private static class Lock { };
    private static Object lock = new Lock();

    // 停止锁
    private static Object haltLock = new Lock();
    static void setRunFinalizersOnExit(boolean run) {
        synchronized (lock) {
            runFinalizersOnExit = run;
        }
    }

    // 添加一个新的关闭挂钩
    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;
        }
    }

    // 运行挂钩线程
    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;
                }
            }
        }
    }
    // 停止的方法
    static void halt(int status) {
        synchronized (haltLock) {
            halt0(status);
        }
    }

    // 本地方法中止延时
    static native void halt0(int status);

    // 调用所有的的终结
    private static native void runAllFinalizers();

    // 实际的关机方法
    // 实际的关机顺序在此定义
    private static void sequence() {
        synchronized (lock) {
            if (state != HOOKS) return;
        }
        runHooks();
        boolean rfoe;
        synchronized (lock) {
            state = FINALIZERS;
            rfoe = runFinalizersOnExit;
        }
        if (rfoe) runAllFinalizers();
    }

    // 终止当前方法的 exit 方法
    static void exit(int status) {
        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(status);
                    } else {
                        runMoreFinalizers = runFinalizersOnExit;
                    }
                    break;
            }
        }
        if (runMoreFinalizers) {
            runAllFinalizers();
            halt(status);
        }
        synchronized (Shutdown.class) {
            sequence();
            halt(status);
        }
    }

    // 终止的方法
    static void shutdown() {
        synchronized (lock) {
            // 检查状态
            switch (state) {
                case RUNNING:       /* Initiate shutdown */
                    state = HOOKS;
                    break;
                case HOOKS:         /* Stall and then return */
                case FINALIZERS:
                    break;
            }
        }
        // 加锁调用
        synchronized (Shutdown.class) {
            sequence();
        }
    }
}

在Runtime的源码中还调用了 ApplicationShutdownHooks类

我们来看一下源码

// 这是一个 用于跟踪和运行通过注册的用户级别关闭挂钩的类
class ApplicationShutdownHooks {
    
    // 套勾集合
    private static IdentityHashMap<Thread, Thread> hooks;
    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) {
            hooks = null;
        }
    }


    private ApplicationShutdownHooks() {}

    // 添加一个新的关闭挂钩。检查关闭状态和钩子本身,但不进行任何安全性检查
    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);
    }

    // 删除以前注册的钩子。与add方法一样,此方法不会进行任何安全检查
    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;
    }

    // 遍历所有应用程序挂钩,为每个要运行的创建一个新线程。挂钩同时运行,并且此方法等待完成
    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) { }
        }
    }
}

总结

  • 实际上 Runtime通过调用另外的2个类中的方法来实现自己的一些方法
  • 通过Runtime可以 快速的得到系统的一些数据
  • 而其中的方法 availableProcessors() 可以用来获取系统的核心数 在多线程中设置线程池的大小用的到
  • 其中的退出方法,其实是调用底层的JVM本地方法的退出方法就是调用 Shutdown的halt() 方法,而halt()方法调用halt0()本地方法
  • 同时也可以加载一些包等
1
https://gitee.com/elonchung/Java-Review.git
git@gitee.com:elonchung/Java-Review.git
elonchung
Java-Review
Java-Review
master

搜索帮助