JAVA Runtime(运行时),主要是指JAVA应用程序运行时的外在环境以及内在环境与外在环境的总称,运行时是一个动态的过程,程序的外在环境,包括了虚拟机、操作系统的环境,而内在环境包括了程序属性的状态、程序对资源使用情况等。
在JAVA中,主要是Runtime类包括了大量对运行时的操作,另外ShutDown类、System类都包括了相关的操作,就从Runtime类开始学习。
首先,Runtime是单例模式的一个类,确保了程序运行时有且只有一个对象在内存中。
Runtime类主要的方法说明:
Runtime. exit():退出程序,注意,System.Exit()实际也是调用这里的方法,Runtime再调用ShutDown.exit()退出
addShutdownHook():添加一个线程在关闭时运行
removeShutdownHook(Thread hook):将原来在关闭时运行的一个线程移除
halt(int status):程序停止运行,其中参数为0表示正常停止,参数为非0表示异常停止
runFinalizersOnExit(boolean value):退出时调用析构函数,true为调用
exec(String command):较常用的一个方法,主要是执行其他程序,返回的对象是进程,即Process
availableProcessors():native方法,主要返回有多少可用的处理器
freeMemory():native方法,返回虚拟机有多少空闲内存
totalMemory()native方法,返回虚拟机总共有多少内存
maxMemory()native方法,返回虚拟机最大内存
gc()native方法,通知虚拟机执行垃圾回收
runFinalization0()native方法,执行虚构函数
load():加载库文件
其中一段代码实现值得我们学习:
public Process exec(String[] cmdarray, String[] envp, File dir)
throwsIOException {
returnnew ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
ProcessBuilder应该是实现了构造者(Builder)模式,它执行某个方法时,返回this,再调用其他方法,代码相对比较简洁,对流程相同,对象不同的代码实现了解耦。
Shutdown类:
Runtime类中对于程序停止与关闭的操作,实际上都交给了ShutDown来处理,
先看ShutDown方法:
halt0(int status):native方法,停止程序
runAllFinalizers():native方法,调用虚构函数释放资源
setRunFinalizersOnExit():设置是否调用析构函数
add(Runnable hook):添加一个程序,在停止程序时执行
remove(Runnable hook):移除一个在程序停止时执行的程序
runHooks():执行那些加载进来在停止时执行的程序
halt(int status):停止执行程序
sequence():执行HOOK的程序,并调用虚构函数析构资源
exit(int status):退出系统
这个类有几个地方值得学习的,首先是加锁的方法:
private static class Lock { };
private static Object lock = new Lock();
synchronized (lock) {
if (state >RUNNING)
throw new IllegalStateException("Shutdown in progress");
hooks.add(hook);
}
我们在程序中也可以考虑这样对对象进行锁定。
其次,是对Hook的处理,这样可以将一段代码以线程的形式存放在某个集合中,等到了特定的时刻再统一执行。
/* Run allregistered shutdown hooks
*/
private static void runHooks() {
/* We needn't bother acquiring the lockjust to read the hooks field,
* since the hooks can't bemodified once shutdown is in progress
*/
for (Runnable hook : hooks) {
try {
hook.run();
} catch(Throwable t) {
if (t instanceof ThreadDeath) {
ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
}
另外,在ProcessBuilder里发现了JAVA的关键字:assert
参数为一个表达式,如果为FALSE时,执行时会报错:Exception in thread "main"java.lang.AssertionError。
看看下面测试代码
public static void main(String[] args) {
System.out.println("测试断言语句");
assert false;
System.out.println("看看能否执行到这里");
}
注意虚拟机必须设置一下参数:-ea
特别说明:assert需要配置参数才有用,在WEB开发上比较麻烦,另外,在生产环境中,如果出现false后就会退出,对整个生产会有影响。最好不要使用,用Junit来代替,特别是在业务处理中,如果在一些核心类、框架接口、工具类中,则使用较为理想,可以考虑使用。
参数的说明如下:
参数 例子 说明
-ea java -ea 打开所有用户类的assertion
-da java -da 关闭所有用户类的assertion
-ea: java -ea:MyClass1 打开MyClass1的assertion
-da: java -da: MyClass1 关闭MyClass1的assertion
-ea: java -ea:pkg1 打开pkg1包的assertion
-da: java -da:pkg1 关闭pkg1包的assertion
-ea:... java -ea:... 打开缺省包(无名包)的assertion
-da:... java -da:... 关闭缺省包(无名包)的assertion
-ea:... java -ea:pkg1... 打开pkg1包和其子包的assertion
-da:... java -da:pkg1... 关闭pkg1包和其子包的assertion
-esa java -esa 打开系统类的assertion
-dsa java -dsa 关闭系统类的assertion
最后看看System类,先看看方法:
console():获得控制台,注意,在Eclipse中,调用这个方法是无法获得的,因为Eclipse的控制台是模拟的。
private static native void setIn0(InputStream in);//设置输入流
private static native void setOut0(PrintStream out);//设置输出流
private static native void setErr0(PrintStream err);//设置错误流
public static native long currentTimeMillis();//获取当前时间毫秒数
public static native long nanoTime();//获取当前时间纳秒数
public static native void arraycopy(Object src, int srcPos,
Objectdest, int destPos,
int length);//数组拷贝
public static native int identityHashCode(Object x);//获取哈希码
private static native PropertiesinitProperties(Properties props);//初始化系统属性
public static PropertiesgetProperties():获取系统属性
setProperties():设置系统属性
clearProperty(String key):清除系统属性
checkKey(String key):非空与非NULL验证
exit(int status):退出系统
gc():通知虚拟机进行垃圾回收
runFinalization():调用虚构函数释放资源
runFinalizersOnExit(boolean value):设置是否退出时执行析构函数
load(String filename):加载库文件,参数是绝对路径
loadLibrary(String libname):加载库文件,参数是文件名(不包括扩展名)
mapLibraryName(String libname):将库文件名映射到系统中
initializeSystemClass():初始化系统类。有意思的是在里面加载了zip类库,一遍使用Zip流处理。
getCallerClass():获取类的调用者