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状态切换图 :
->
ok, Runtime 到此结束了, 这个类主要涉及其他的两个ApplicationShutdown.java, 和Shutdown.java 两个包级别的类
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!