深入研究java.lang.Runtime类
|
前言:Java的类库日益庞大,所包含的类和接口也不计其数。但其中有一些非常重要的类和接口,是Java类库中的核心部分。常见的有String、Object、Class、Collection、ClassLoader、Runtime、Process...,熟悉这些类是学好Java的基础。而这些类一般不容易理解,需要做深入的研究和实践才能掌握。下面是我对这些类理解和使用的一些总结。欢迎你在阅读后将你宝贵的意见和读后感留下!
一、概述
二、API预览
三、常见的应用 1、内存管理: //此实例来自《java核心技术》卷一 mem2 = r.freeMemory(); //discard Intergers 编译后运行结果如下(不同的机器不同时间运行的结果也不一定一样):
2、执行其他程序 //此实例来自《Java核心技术》卷一 ecec()还有其他几种形式,例子中演示的是最常用的一种。ecec()方法返回Process对象后,在新程序开始运行后就可以使用Process的方法了。可以用destory()方法杀死子进程,也可以使用waitFor()方法等待程序直到子程序结束,exitValue()方法返回子进程结束时返回的值。如果没有错误,将返回0,否则返回非0。下面是关于ecec()方法的例子的改进版本。例子被修改为等待,直到运行的进程退出: //此实例来自《Java核心技术》卷一
当子进程正在运行时,可以对标准输入输出进行读写。getOutputStream()方法和getInPutStream()方法返回对子进程的标准输入和输出。
java.lang | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| 方法摘要 | |
|---|---|
void |
addShutdownHook(Thread hook) 注册新的虚拟机来关闭挂钩。 |
int |
availableProcessors() 向 Java 虚拟机返回可用处理器的数目。 |
Process |
exec(String command) 在单独的进程中执行指定的字符串命令。 |
Process |
exec(String[] cmdarray) 在单独的进程中执行指定命令和变量。 |
Process |
exec(String[] cmdarray, String[] envp) 在指定环境的独立进程中执行指定命令和变量。 |
Process |
exec(String[] cmdarray, String[] envp, File dir) 在指定环境和工作目录的独立进程中执行指定的命令和变量。 |
Process |
exec(String command, String[] envp) 在指定环境的单独进程中执行指定的字符串命令。 |
Process |
exec(String command, String[] envp, File dir) 在有指定环境和工作目录的独立进程中执行指定的字符串命令。 |
void |
exit(int status) 通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。 |
long |
freeMemory() 返回 Java 虚拟机中的空闲内存量。 |
void |
gc() 运行垃圾回收器。 |
InputStream |
getLocalizedInputStream(InputStream in) 已过时。 从 JDK 1.1 开始,将本地编码字节流转换为 Unicode 字符流的首选方法是使用 InputStreamReader 和 BufferedReader 类。 |
OutputStream |
getLocalizedOutputStream(OutputStream out) 已过时。 从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 类。 |
static Runtime |
getRuntime() 返回与当前 Java 应用程序相关的运行时对象。 |
void |
halt(int status) 强行终止目前正在运行的 Java 虚拟机。 |
void |
load(String filename) 加载作为动态库的指定文件名。 |
void |
loadLibrary(String libname) 加载具有指定库名的动态库。 |
long |
maxMemory() 返回 Java 虚拟机试图使用的最大内存量。 |
boolean |
removeShutdownHook(Thread hook) 取消注册某个先前已注册的虚拟机关闭挂钩。 |
void |
runFinalization() 运行挂起 finalization 的所有对象的终止方法。 |
static void |
runFinalizersOnExit(boolean value) 已过时。 此方法本身具有不安全性。它可能对正在使用的对象调用终结方法,而其他线程正在操作这些对象,从而导致不正确的行为或死锁。 |
long |
totalMemory() 返回 Java 虚拟机中的内存总量。 |
void |
traceInstructions(boolean on) 启用/禁用指令跟踪。 |
void |
traceMethodCalls(boolean on) 启用/禁用方法调用跟踪。 |
| 从类 java.lang.Object 继承的方法 |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| 方法详细信息 |
|---|
getRuntime
public static Runtime getRuntime()
- 返回与当前 Java 应用程序相关的运行时对象。
Runtime类的大多数方法是实例方法,并且必须根据当前的运行时对象对其进行调用。- 返回:
- 与当前 Java 应用程序相关的
Runtime对象。
exit
public void exit(int status)
- 通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。此方法从不正常返回。可以将变量作为一个状态码;根据惯例,非零的状态码表示非正常终止。
虚拟机的关闭序列包含两个阶段。在第一个阶段中,会以某种未指定的顺序启动所有已注册的
关闭挂钩(如果有的话),并且允许它们同时运行直至结束。在第二个阶段中,如果已启用退出终结,则运行所有未调用的终结方法。一旦完成这个阶段,虚拟机就会暂停。如果在虚拟机已开始其关闭序列后才调用此方法,那么若正在运行关闭挂钩,则将无限期地阻断此方法。如果已经运行完关闭挂钩,并且已启用退出终结 (on-exit finalization),那么此方法将利用给定的状态码(如果状态码是非零值)暂停虚拟机;否则将无限期地阻断虚拟机。
System.exit方法是调用此方法的一种传统而便捷的方式。- 参数:
status- 终止状态。按照惯例,非零的状态码表明非正常终止。- 抛出:
SecurityException- 如果安全管理器存在,并且其checkExit方法不允许存在指定的状态- 另请参见:
SecurityException,SecurityManager.checkExit(int),addShutdownHook(java.lang.Thread),removeShutdownHook(java.lang.Thread),runFinalizersOnExit(boolean),halt(int)
addShutdownHook
public void addShutdownHook(Thread hook)
- 注册新的虚拟机来关闭挂钩。
Java 虚拟机会为了响应以下两类事件而关闭:
- 程序正常退出,这发生在最后的非守护线程退出时,或者在调用
exit(等同于System.exit)方法时。或者, - 为响应用户中断而终止 虚拟机,如键入 ^C;或发生系统事件,比如用户注销或系统关闭。
关闭挂钩 只是一个已初始化但尚未启动的线程。虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。运行完所有的挂钩后,如果已启用退出终结,那么虚拟机接着会运行所有未调用的终结方法。最后,虚拟机会暂停。注意,关闭序列期间会继续运行守护线程,如果通过调用
exit方法来发起关闭序列,那么也会继续运行非守护线程。一旦开始了关闭序列,则只能通过调用
halt方法来停止这个序列,此方法可强行终止虚拟机。一旦开始了关闭序列,则不可能注册新的关闭挂钩或取消注册先前已注册的挂钩。尝试执行这些操作会导致抛出
IllegalStateException。关闭挂钩可在虚拟机生命周期中的特定时间运行,因此应保护性地对其进行编码。特别是应将关闭挂钩编写为线程安全的,并尽可能地避免死锁。关闭挂钩还应该不盲目地依靠某些服务,这些服务可能已注册了自己的关闭挂钩,所以其本身可能正处于关闭进程中。
关闭挂钩应该快速地完成其工作。当程序调用
exit时,虚拟机应该迅速地关闭并退出。由于用户注销或系统关闭而终止虚拟机时,底层的操作系统可能只允许在固定的时间内关闭并退出。因此在关闭挂钩中尝试进行任何用户交互或执行长时间的计算都是不明智的。与其他所有线程一样,通过调用线程
ThreadGroup对象的uncaughtException方法,可在关闭挂钩中处理未捕获的异常。此方法的默认实现是将该异常的堆栈跟踪 (stack trace) 打印至System.err并终止线程;它不会导致虚拟机退出或暂停。仅在很少的情况下,虚拟机可能会中止,也就是没有完全关闭就停止运行。虚拟机被外部终止时会出现这种现象,比如在 Unix 上使用 SIGKILL 信号或者在 Microsoft Windows 上调用 TerminateProcess。如果由于内部数据结构损坏或试图访问不存在的内存而导致本机方法执行错误,那么可能也会中止虚拟机。如果虚拟机中止,则无法保证是否将运行关闭挂钩。
- 参数:
hook- 一个已初始化但尚未启动的Thread对象- 抛出:
IllegalArgumentException- 如果指定的挂钩已注册,或者可以确定挂钩正在运行或者已运行完毕IllegalStateException- 如果虚拟机已经处于关闭进程中SecurityException- 如果安全管理器存在并且拒绝RuntimePermission("shutdownHooks")- 从以下版本开始:
- 1.3
- 另请参见:
removeShutdownHook(java.lang.Thread),halt(int),exit(int)
- 程序正常退出,这发生在最后的非守护线程退出时,或者在调用
removeShutdownHook
public boolean removeShutdownHook(Thread hook)
- 取消注册某个先前已注册的虚拟机关闭挂钩。
- 参数:
hook- 要删除的挂钩- 返回:
- 如果指定的挂钩先前已注册并且成功地取消注册,则返回 true,其他情况返回 false。
- 抛出:
IllegalStateException- 如果虚拟机已经处于关闭进程中SecurityException- 如果安全管理器存在并且拒绝RuntimePermission("shutdownHooks")- 从以下版本开始:
- 1.3
- 另请参见:
addShutdownHook(java.lang.Thread),exit(int)
halt
public void halt(int status)
- 强行终止目前正在运行的 Java 虚拟机。此方法从不正常返回。
应小心使用此方法。与
exit方法不同,此方法不会启动关闭挂钩,并且如果已启用退出终结,此方法也不会运行未调用的终结方法。如果已经发起关闭序列,那么此方法不会等待所有正在运行的关闭挂钩或终结方法完成其工作。- 参数:
status- 终止状态。按照惯例,非零的状态码表明非正常终止。如果已经调用了exit(System.exit也一样)方法,那么该状态码将重写已传递至此方法的状态码。- 抛出:
SecurityException- 如果安全管理器存在,并且其checkExit方法不允许具有指定状态时退出- 从以下版本开始:
- 1.3
- 另请参见:
exit(int),addShutdownHook(java.lang.Thread),removeShutdownHook(java.lang.Thread)
runFinalizersOnExit
@Deprecated public static void runFinalizersOnExit(boolean value)
- 已过时。 此方法本身具有不安全性。它可能对正在使用的对象调用终结方法,而其他线程正在操作这些对象,从而导致不正确的行为或死锁。
- 在退出时启用或禁用终结;这样做可指定拥有未被自动调用终结方法的所有对象的终结方法,并将在退出 Java 运行时前运行此终结方法。默认情况下,禁用退出终结。
如果有安全管理器,则首先使用 0 作为变量来调用其
checkExit方法,以确保允许退出。这可能会导致 SecurityException。- 参数:
value- 如果启用退出时终结,则该参数为 true,如果禁用退出时终结,则该参数为 false- 抛出:
SecurityException- 如果安全管理器存在并且其checkExit方法不允许退出。- 从以下版本开始:
- JDK1.1
- 另请参见:
exit(int),gc(),SecurityManager.checkExit(int)
- 在退出时启用或禁用终结;这样做可指定拥有未被自动调用终结方法的所有对象的终结方法,并将在退出 Java 运行时前运行此终结方法。默认情况下,禁用退出终结。
exec
public Process exec(String command) throws IOException
- 在单独的进程中执行指定的字符串命令。
这是一个很有用的方法。对于 exec(command) 形式的调用而言,其行为与调用
exec(command, null, null) 完全相同。- 参数:
command- 一条指定的系统命令。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果command为nullIllegalArgumentException- 如果command为空- 另请参见:
exec(String[], String[], File),ProcessBuilder
exec
public Process exec(String command, String[] envp) throws IOException
- 在指定环境的单独进程中执行指定的字符串命令。
这是一个很有用的方法。对于 exec(command, envp) 形式的调用而言,其行为与调用
exec(command, envp, null) 完全相同。- 参数:
command- 一条指定的系统命令。envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value;如果子进程应该继承当前进程的环境,或该参数为 null。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果command为null,或envp的元素之一为nullIllegalArgumentException- 如果command为空- 另请参见:
exec(String[], String[], File),ProcessBuilder
exec
public Process exec(String command, String[] envp, File dir) throws IOException
- 在有指定环境和工作目录的独立进程中执行指定的字符串命令。
这是一个很有用的方法。对于 exec(command, envp, dir) 形式的调用而言,其行为与调用
exec(cmdarray, envp, dir) 完全相同,其中cmdarray是command中所有标记的数组。更准确地说,可以使用通过调用
new创建的StringTokenizer(command)StringTokenizer将command字符串拆解成标记,调用时不对字符类别做进一步的修改。然后将标记生成器所生成的标记以相同的顺序放入新的字符串数组cmdarray中。- 参数:
command- 一条指定的系统命令。envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value;如果子进程应该继承当前进程的环境,或该参数为 null。dir- 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果command为null,或者envp的某个元素为nullIllegalArgumentException- 如果command为空- 从以下版本开始:
- 1.3
- 另请参见:
ProcessBuilder
exec
public Process exec(String[] cmdarray) throws IOException
- 在单独的进程中执行指定命令和变量。
这是一个很有用的方法。对于 exec(cmdarray) 形式的调用而言,其行为与调用
exec(cmdarray, null, null) 完全相同。- 参数:
cmdarray- 包含所调用命令及其参数的数组。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果cmdarray为null,或者cmdarray的某个元素为nullIndexOutOfBoundsException- 如果cmdarray是一个空数组(长度为0)- 另请参见:
ProcessBuilder
exec
public Process exec(String[] cmdarray, String[] envp) throws IOException
- 在指定环境的独立进程中执行指定命令和变量。
这是一个很有用的方法。对于 exec(cmdarray, envp) 形式的调用而言,其行为与调用
exec(cmdarray, envp, null) 完全相同。- 参数:
cmdarray- 包含所调用命令及其参数的数组。envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value;如果子进程应该继承当前进程的环境,或该参数为 null。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果cmdarray为null,或者cmdarray的某个元素为null,或者envp的某个元素为nullIndexOutOfBoundsException- 如果cmdarray是一个空数组(长度为0)- 另请参见:
ProcessBuilder
exec
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException
- 在指定环境和工作目录的独立进程中执行指定的命令和变量。
给定的字符串数组
cmdarray表示一个命令行标记,字符串数组envp则表示“环境”变量设置,此方法会创建一个新进程,而指定的命令就在这个进程中执行。此方法检查
cmdarray是否是一条有效的操作系统命令。哪些命令有效取决于系统,但是该命令至少必须有一个非 null 字符串的非空列表。如果 envp 为 null,那么子进程会继承当前进程的环境设置。
ProcessBuilder.start()现在是启用一个具有已修改环境的进程的首选方法。dir 指定了新子进程的工作目录。如果 dir 为 null,那么子进程会继承当前进程的当前工作目录。
如果安全管理器存在,则用数组
cmdarray的第一个元素作为变量来调用安全管理器的checkExec方法。这可能导致抛出SecurityException。启动操作系统进程的方式完全取决于系统。其中有很多方面会导致错误:
- 未找到操作系统程序文件。
- 对程序文件的访问被拒绝。
- 工作目录不存在。
这些情况都会抛出一个异常。该异常的具体特性取决于系统,但它总是
IOException的一个子类。- 参数:
cmdarray- 包含所调用命令及其参数的数组。envp- 字符串数组,其中每个元素的环境变量的设置格式为 name=value,如果子进程应该继承当前进程的环境,或该参数为 null。dir- 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。- 返回:
- 一个新的
Process对象,用于管理子进程 - 抛出:
SecurityException- 如果安全管理器存在,并且其checkExec方法不允许创建子进程IOException- 如果发生 I/O 错误NullPointerException- 如果cmdarray为null,或者cmdarray的某个元素为null,抑或envp的某个元素为nullIndexOutOfBoundsException- 如果cmdarray是一个空数组(长度为0)- 从以下版本开始:
- 1.3
- 另请参见:
ProcessBuilder
availableProcessors
public int availableProcessors()
- 向 Java 虚拟机返回可用处理器的数目。
该值在特定的虚拟机调用期间可能发生更改。因此,对可用处理器数目很敏感的应用程序应该不定期地轮询该属性,并相应地调整其资源用法。
- 返回:
- 虚拟机可用的最大处理器数目;从不小于 1
- 从以下版本开始:
- 1.4
freeMemory
public long freeMemory()
- 返回 Java 虚拟机中的空闲内存量。调用
gc方法可能导致freeMemory返回值的增加。- 返回:
- 供将来分配对象使用的当前可用内存的近似总量,以字节为单位。
totalMemory
public long totalMemory()
- 返回 Java 虚拟机中的内存总量。此方法返回的值可能随时间的推移而变化,这取决于主机环境。
注意,保存任意给定类型的一个对象所需的内存量可能取决于实现方法。
- 返回:
- 目前为当前和后续对象提供的内存总量,以字节为单位。
maxMemory
public long maxMemory()
- 返回 Java 虚拟机试图使用的最大内存量。如果内存本身没有限制,则返回值
Long.MAX_VALUE。- 返回:
- 虚拟机试图使用的最大内存量,以字节为单位。
- 从以下版本开始:
- 1.4
gc
public void gc()
- 运行垃圾回收器。调用此方法意味着 Java 虚拟机做了一些努力来回收未用对象,以便能够快速地重用这些对象当前占用的内存。当控制从方法调用中返回时,虚拟机已经尽最大努力回收了所有丢弃的对象。
名称
gc代表“垃圾回收器”。虚拟机根据需要在单独的线程中自动执行回收过程,甚至不用显式调用gc方法。方法
System.gc()是调用此方法的一种传统而便捷的方式。
runFinalization
public void runFinalization()
- 运行挂起 finalization 的所有对象的终止方法。调用此方法意味着 Java 虚拟机做了一些努力运行已被丢弃对象的
finalize方法,但是这些对象的finalize方法还没有运行。当控制从方法调用中返回时,Java 虚拟机已经尽最大努力去完成所有未执行的终止方法。如果不显式调用
runFinalization方法,则 Java 虚拟机会根据需要在单独的线程中自动执行此终止过程。方法
System.runFinalization()是调用此方法的一种传统而便捷的方式。- 另请参见:
Object.finalize()
traceInstructions
public void traceInstructions(boolean on)
- 启用/禁用指令跟踪。如果
boolean变量为true,则执行此方法意味着让 Java 虚拟机发送虚拟机中每条指令执行的调试信息。该信息的格式,以及虚拟机所发送的文件或其他输出流的格式取决于主机的环境。如果虚拟机不支持此功能,则忽略这一 请求。跟踪输出的目的地取决于系统。如果
boolean变量为false,则执行此方法时将使 Java 虚拟机停止执行详细的指令跟踪。- 参数:
on- 为true时启用指令跟踪;为false时则禁用此功能。
traceMethodCalls
public void traceMethodCalls(boolean on)
- 启用/禁用方法调用跟踪。如果
boolean变量为true,则执行此方法意味着让 Java 虚拟机发送虚拟机中每个方法的调试信息。该信息的格式,以及虚拟机所发送的文件或其他输出流的格式取决于主机的环境。如果虚拟机不支持此功能,则忽略这一请求。使用变量 false 调用此方法意味着虚拟机停止发送每个调用的调试信息。
- 参数:
on- 为true时启用指令跟踪;为false时则禁用此功能。
load
public void load(String filename)
- 加载作为动态库的指定文件名。文件名变量必须是一个完整的路径名。对于
java_g,会自动在 "_g" 前面插入 ".so"(例如Runtime.getRuntime().load("/home/avh/lib/libX11.so");)。首先,如果有安全管理器,则用
filename作为参数调用checkLink方法。这可能导致安全异常。这与
loadLibrary(String)方法类似,但它接受通用文件名作为变量,而不仅仅是库名,从而能够加载所有的本机代码文件。方法
System.load(String)是调用此方法的一种传统而便捷的方式。- 参数:
filename- 要加载的文件。- 抛出:
SecurityException- 如果安全管理器存在,并且其checkLink方法不允许加载指定的动态库UnsatisfiedLinkError- 如果文件不存在。NullPointerException- 如果filename为null- 另请参见:
getRuntime(),SecurityException,SecurityManager.checkLink(java.lang.String)
loadLibrary
public void loadLibrary(String libname)
- 加载具有指定库名的动态库。从以前获取库文件的本地文件系统中加载含有本机代码的文件。这一过程的细节取决于实现方法。可以以某种特定于系统的方式完成从库名到特定文件名的映射。
首先,如果有安全管理器,则用
libname作为参数调用checkLink方法。这可能导致安全性异常。方法
System.loadLibrary(String)是调用此方法的一种传统而便捷的方式。如果在某个类实现中使用本机方法,则标准的策略是将本机代码放入一个库文件中(称为LibFile),然后在类声明中放入一个静态的初始值设定项:
当加载并初始化这个类时,也将加载实现本机方法所需的本机代码。static { System.loadLibrary("LibFile"); }如果用相同库名多次调用此方法,则忽略第二次及后续的调用。
- 参数:
libname- 库名。- 抛出:
SecurityException- 如果安全管理器存在,并且其checkLink方法不允许加载指定的动态库UnsatisfiedLinkError- 如果库不存在。NullPointerException- 如果libname为null- 另请参见:
SecurityException,SecurityManager.checkLink(java.lang.String)
getLocalizedInputStream
@Deprecated public InputStream getLocalizedInputStream(InputStream in)
- 已过时。 从 JDK 1.1 开始,将本地编码字节流转换为 Unicode 字符流的首选方法是使用
InputStreamReader和BufferedReader类。- 创建输入流的本地化版本。此方法获取
InputStream,并返回除本地化外其他所有方面都和变量等效的InputStream,这些方面包括:作为本地字符集中的字符从流中被读取,并将它们从本地字符集自动转换为 Unicode。如果参数已经是本地化流,则可作为结果返回。
- 参数:
in- 要本地化的 InputStream- 返回:
- 已本地化的输入流
- 另请参见:
InputStream,BufferedReader.BufferedReader(java.io.Reader),InputStreamReader.InputStreamReader(java.io.InputStream)
- 创建输入流的本地化版本。此方法获取
getLocalizedOutputStream
@Deprecated public OutputStream getLocalizedOutputStream(OutputStream out)
- 已过时。 从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用
OutputStreamWriter、BufferedWriter和PrintWriter类。- 创建输出流的本地化版本。此方法获取
OutputStream,并返回除本地化外其他所有方面都和变量等效的OutputStream,这些方面包括:作为 Unicode 字符被写入流中,并被自动转换为本地字符集。如果参数已经是本地流,则可作为结果返回。
- 参数:
out- 要本地化的 OutputStream- 返回:
- 已本地化的输出流
- 另请参见:
OutputStream,BufferedWriter.BufferedWriter(java.io.Writer),OutputStreamWriter.OutputStreamWriter(java.io.OutputStream),PrintWriter.PrintWriter(java.io.OutputStream)
- 创建输出流的本地化版本。此方法获取



java.lang.Runtime
leizhimin
博客统计信息
热门文章
最新评论
友情链接