Java程序多进程运行模式的实例分析
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。而有的时候,我们需要通过java代码启动多个java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。 在Java中我们可以使用两种方法来实现这种要求。最简.
一般我们在java中运行其它类中的方法时,无论是静态调用,还是动态调用,都是在当前的进程中执行的,也就是说,只有一个java虚拟机实例在运行。而有的时候,我们需要通过java代码启动多个java子进程。这样做虽然占用了一些系统资源,但会使程序更加稳定,因为新启动的程序是在不同的虚拟机进程中运行的,如果有一个进程发生异常,并不影响其它的子进程。
在Java中我们可以使用两种方法来实现这种要求。最简单的方法就是通过Runtime中的exec方法执行java classname。如果执行成功,这个方法返回一个Process对象,如果执行失败,将抛出一个IOException错误。下面让我们来看一个简单的例子。
// Test1.java文件
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileOutputStream fOut = new FileOutputStream("c:/Test1.txt");
fOut.close();
System.out.println("被调用成功!");
}
}
// Test_Exec.java
import java.io.IOException;
public class Test_Exec {
public static void main(String[] args) throws IOException {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test1");
}
}
通过java Test_Exec运行程序后,发现在C盘多了个Test1.txt文件,但在控制台中并未出现"被调用成功!"的输出信息。因此可以断定,Test已经被执行成功,但因为某种原因,Test的输出信息未在Test_Exec的控制台中输出。这个原因也很简单,因为使用exec建立的是Test_Exec的子进程,这个子进程并没有自己的控制台,因此,它并不会输出任何信息。
如果要输出子进程的输出信息,可以通过Process中的getInputStream得到子进程的输出流(在子进程中输出,在父进程中就是输入),然后将子进程中的输出流从父进程的控制台输出。具体的实现代码如下如示:
// Test_Exec_Out.java
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test_Exec_Out {
public static void main(String[] args) throws IOException {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test1");
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
}
}
从上面的代码可以看出,在Test_Exec_Out.java中通过按行读取子进程的输出信息,然后在Test_Exec_Out中按每行进行输出。 上面讨论的是如何得到子进程的输出信息。那么,除了输出信息,还有输入信息。既然子进程没有自己的控制台,那么输入信息也得由父进程提供。我们可以通过Process的getOutputStream方法来为子进程提供输入信息(即由父进程向子进程输入信息,而不是由控制台输入信息)。我们可以看看如下的代码:
// Test2.java文件
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("由父进程输入的信息:" + br.readLine());
}
}
// Test_Exec_In.java
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Test_Exec_In {
public static void main(String[] args) throws IOException {
Runtime run = Runtime.getRuntime();
Process p = run.exec("java test2");
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(p.getOutputStream()));
bw.write("向子进程输出信息");
bw.flush();
bw.close(); // 必须得关闭流,否则无法向子进程中输入信息
// System.in.read();
}
}
从以上代码可以看出,Test1得到由Test_Exec_In发过来的信息,并将其输出。当你不加bw.flash()和bw.close()时,信息将无法到达子进程,也就是说子进程进入阻塞状态,但由于父进程已经退出了,因此,子进程也跟着退出了。如果要证明这一点,可以在最后加上System.in.read(),然后通过任务管理器(在windows下)查看java进程,你会发现如果加上bw.flush()和bw.close(),只有一个java进程存在,如果去掉它们,就有两个java进程存在。这是因为,如果将信息传给Test2,在得到信息后,Test2就退出了。在这里有一点需要说明一下,exec的执行是异步的,并不会因为执行的某个程序阻塞而停止执行下面的代码。因此,可以在运行test2后,仍可以执行下面的代码。
exec方法经过了多次的重载。上面使用的只是它的一种重载。它还可以将命令和参数分开,如exec("java.test2")可以写成exec("java", "test2")。exec还可以通过指定的环境变量运行不同配置的java虚拟机。
除了使用Runtime的exec方法建立子进程外,还可以通过ProcessBuilder建立子进程。ProcessBuilder的使用方法如下:
// Test_Exec_Out.java
import java.io.IOException;
public class Test_Exec_Out {
public static void main(String[] args) throws IOException {
ProcessBuilder pb = new ProcessBuilder("java", "test1");
Process p = pb.start();
}
}
在建立子进程上,ProcessBuilder和Runtime类似,不同的ProcessBuilder使用start()方法启动子进程,而Runtime使用exec方法启动子进程。得到Process后,它们的操作就完全一样的。
ProcessBuilder和Runtime一样,也可设置可执行文件的环境信息、工作目录等。
ProcessBuilder pb = new ProcessBuilder("Command", "arg2", "arg2", ’’’);
// 设置环境变量
Map env = pb.environment();
env.put("key1", "value1");
env.remove("key2");
env.put("key2", env.get("key1") + "_test");
pb.directory("../abcd"); // 设置工作目录
Process p = pb.start(); // 建立子进程
参考源码
/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang;
import java.io.*;
import java.util.StringTokenizer;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/**
* 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 {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class <code>Runtime</code> are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the <code>Runtime</code> object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
/**
* Terminates the currently running Java virtual machine by initiating its
* shutdown sequence. This method never returns normally. The argument
* serves as a status code; by convention, a nonzero status code indicates
* abnormal termination.
*
* <p> The virtual machine's shutdown sequence consists of two phases. In
* the first phase all registered {@link #addShutdownHook shutdown hooks},
* if any, are started in some unspecified order and allowed to run
* concurrently until they finish. In the second phase all uninvoked
* finalizers are run if {@link #runFinalizersOnExit finalization-on-exit}
* has been enabled. Once this is done the virtual machine {@link #halt
* halts}.
*
* <p> If this method is invoked after the virtual machine has begun its
* shutdown sequence then if shutdown hooks are being run this method will
* block indefinitely. If shutdown hooks have already been run and on-exit
* finalization has been enabled then this method halts the virtual machine
* with the given status code if the status is nonzero; otherwise, it
* blocks indefinitely.
*
* <p> The <tt>{@link System#exit(int) System.exit}</tt> method is the
* conventional and convenient means of invoking this method. <p>
*
* @param status
* Termination status. By convention, a nonzero status code
* indicates abnormal termination.
*
* @throws SecurityException
* If a security manager is present and its <tt>{@link
* SecurityManager#checkExit checkExit}</tt> method does not permit
* exiting with the specified status
*
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkExit(int)
* @see #addShutdownHook
* @see #removeShutdownHook
* @see #runFinalizersOnExit
* @see #halt(int)
*/
public void exit(int status) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkExit(status);
}
Shutdown.exit(status);
}
/**
* Registers a new virtual-machine shutdown hook.
*
* <p> The Java virtual machine <i>shuts down</i> in response to two kinds
* of events:
*
* <ul>
*
* <li> The program <i>exits</i> normally, when the last non-daemon
* thread exits or when the <tt>{@link #exit exit}</tt> (equivalently,
* {@link System#exit(int) System.exit}) method is invoked, or
*
* <li> The virtual machine is <i>terminated</i> in response to a
* user interrupt, such as typing <tt>^C</tt>, or a system-wide event,
* such as user logoff or system shutdown.
*
* </ul>
*
* <p> A <i>shutdown hook</i> is simply an initialized but unstarted
* thread. When the virtual machine begins its shutdown sequence it will
* start all registered shutdown hooks in some unspecified order and let
* them run concurrently. When all the hooks have finished it will then
* run all uninvoked finalizers if finalization-on-exit has been enabled.
* Finally, the virtual machine will halt. Note that daemon threads will
* continue to run during the shutdown sequence, as will non-daemon threads
* if shutdown was initiated by invoking the <tt>{@link #exit exit}</tt>
* method.
*
* <p> Once the shutdown sequence has begun it can be stopped only by
* invoking the <tt>{@link #halt halt}</tt> method, which forcibly
* terminates the virtual machine.
*
* <p> Once the shutdown sequence has begun it is impossible to register a
* new shutdown hook or de-register a previously-registered hook.
* Attempting either of these operations will cause an
* <tt>{@link IllegalStateException}</tt> to be thrown.
*
* <p> Shutdown hooks run at a delicate time in the life cycle of a virtual
* machine and should therefore be coded defensively. They should, in
* particular, be written to be thread-safe and to avoid deadlocks insofar
* as possible. They should also not rely blindly upon services that may
* have registered their own shutdown hooks and therefore may themselves in
* the process of shutting down. Attempts to use other thread-based
* services such as the AWT event-dispatch thread, for example, may lead to
* deadlocks.
*
* <p> Shutdown hooks should also finish their work quickly. When a
* program invokes <tt>{@link #exit exit}</tt> the expectation is
* that the virtual machine will promptly shut down and exit. When the
* virtual machine is terminated due to user logoff or system shutdown the
* underlying operating system may only allow a fixed amount of time in
* which to shut down and exit. It is therefore inadvisable to attempt any
* user interaction or to perform a long-running computation in a shutdown
* hook.
*
* <p> Uncaught exceptions are handled in shutdown hooks just as in any
* other thread, by invoking the <tt>{@link ThreadGroup#uncaughtException
* uncaughtException}</tt> method of the thread's <tt>{@link
* ThreadGroup}</tt> object. The default implementation of this method
* prints the exception's stack trace to <tt>{@link System#err}</tt> and
* terminates the thread; it does not cause the virtual machine to exit or
* halt.
*
* <p> In rare circumstances the virtual machine may <i>abort</i>, that is,
* stop running without shutting down cleanly. This occurs when the
* virtual machine is terminated externally, for example with the
* <tt>SIGKILL</tt> signal on Unix or the <tt>TerminateProcess</tt> call on
* Microsoft Windows. The virtual machine may also abort if a native
* method goes awry by, for example, corrupting internal data structures or
* attempting to access nonexistent memory. If the virtual machine aborts
* then no guarantee can be made about whether or not any shutdown hooks
* will be run. <p>
*
* @param hook
* An initialized but unstarted <tt>{@link Thread}</tt> object
*
* @throws IllegalArgumentException
* If the specified hook has already been registered,
* or if it can be determined that the hook is already running or
* has already been run
*
* @throws IllegalStateException
* If the virtual machine is already in the process
* of shutting down
*
* @throws SecurityException
* If a security manager is present and it denies
* <tt>{@link RuntimePermission}("shutdownHooks")</tt>
*
* @see #removeShutdownHook
* @see #halt(int)
* @see #exit(int)
* @since 1.3
*/
public void addShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
ApplicationShutdownHooks.add(hook);
}
/**
* De-registers a previously-registered virtual-machine shutdown hook. <p>
*
* @param hook the hook to remove
* @return <tt>true</tt> if the specified hook had previously been
* registered and was successfully de-registered, <tt>false</tt>
* otherwise.
*
* @throws IllegalStateException
* If the virtual machine is already in the process of shutting
* down
*
* @throws SecurityException
* If a security manager is present and it denies
* <tt>{@link RuntimePermission}("shutdownHooks")</tt>
*
* @see #addShutdownHook
* @see #exit(int)
* @since 1.3
*/
public boolean removeShutdownHook(Thread hook) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("shutdownHooks"));
}
return ApplicationShutdownHooks.remove(hook);
}
/**
* Forcibly terminates the currently running Java virtual machine. This
* method never returns normally.
*
* <p> This method should be used with extreme caution. Unlike the
* <tt>{@link #exit exit}</tt> method, this method does not cause shutdown
* hooks to be started and does not run uninvoked finalizers if
* finalization-on-exit has been enabled. If the shutdown sequence has
* already been initiated then this method does not wait for any running
* shutdown hooks or finalizers to finish their work. <p>
*
* @param status
* Termination status. By convention, a nonzero status code
* indicates abnormal termination. If the <tt>{@link Runtime#exit
* exit}</tt> (equivalently, <tt>{@link System#exit(int)
* System.exit}</tt>) method has already been invoked then this
* status code will override the status code passed to that method.
*
* @throws SecurityException
* If a security manager is present and its <tt>{@link
* SecurityManager#checkExit checkExit}</tt> method does not permit
* an exit with the specified status
*
* @see #exit
* @see #addShutdownHook
* @see #removeShutdownHook
* @since 1.3
*/
public void halt(int status) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkExit(status);
}
Shutdown.halt(status);
}
/**
* Enable or disable finalization on exit; doing so specifies that the
* finalizers of all objects that have finalizers that have not yet been
* automatically invoked are to be run before the Java runtime exits.
* By default, finalization on exit is disabled.
*
* <p>If there is a security manager,
* its <code>checkExit</code> method is first called
* with 0 as its argument to ensure the exit is allowed.
* This could result in a SecurityException.
*
* @param value true to enable finalization on exit, false to disable
* @deprecated This method is inherently unsafe. It may result in
* finalizers being called on live objects while other threads are
* concurrently manipulating those objects, resulting in erratic
* behavior or deadlock.
*
* @throws SecurityException
* if a security manager exists and its <code>checkExit</code>
* method doesn't allow the exit.
*
* @see java.lang.Runtime#exit(int)
* @see java.lang.Runtime#gc()
* @see java.lang.SecurityManager#checkExit(int)
* @since JDK1.1
*/
@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);
}
/**
* Executes the specified string command in a separate process.
*
* <p>This is a convenience method. An invocation of the form
* <tt>exec(command)</tt>
* behaves in exactly the same way as the invocation
* <tt>{@link #exec(String, String[], File) exec}(command, null, null)</tt>.
*
* @param command a specified system command.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>command</code> is <code>null</code>
*
* @throws IllegalArgumentException
* If <code>command</code> is empty
*
* @see #exec(String[], String[], File)
* @see ProcessBuilder
*/
public Process exec(String command) throws IOException {
return exec(command, null, null);
}
/**
* Executes the specified string command in a separate process with the
* specified environment.
*
* <p>This is a convenience method. An invocation of the form
* <tt>exec(command, envp)</tt>
* behaves in exactly the same way as the invocation
* <tt>{@link #exec(String, String[], File) exec}(command, envp, null)</tt>.
*
* @param command a specified system command.
*
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* <tt>null</tt> if the subprocess should inherit
* the environment of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>command</code> is <code>null</code>,
* or one of the elements of <code>envp</code> is <code>null</code>
*
* @throws IllegalArgumentException
* If <code>command</code> is empty
*
* @see #exec(String[], String[], File)
* @see ProcessBuilder
*/
public Process exec(String command, String[] envp) throws IOException {
return exec(command, envp, null);
}
/**
* Executes the specified string command in a separate process with the
* specified environment and working directory.
*
* <p>This is a convenience method. An invocation of the form
* <tt>exec(command, envp, dir)</tt>
* behaves in exactly the same way as the invocation
* <tt>{@link #exec(String[], String[], File) exec}(cmdarray, envp, dir)</tt>,
* where <code>cmdarray</code> is an array of all the tokens in
* <code>command</code>.
*
* <p>More precisely, the <code>command</code> string is broken
* into tokens using a {@link StringTokenizer} created by the call
* <code>new {@link StringTokenizer}(command)</code> with no
* further modification of the character categories. The tokens
* produced by the tokenizer are then placed in the new string
* array <code>cmdarray</code>, in the same order.
*
* @param command a specified system command.
*
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* <tt>null</tt> if the subprocess should inherit
* the environment of the current process.
*
* @param dir the working directory of the subprocess, or
* <tt>null</tt> if the subprocess should inherit
* the working directory of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>command</code> is <code>null</code>,
* or one of the elements of <code>envp</code> is <code>null</code>
*
* @throws IllegalArgumentException
* If <code>command</code> is empty
*
* @see ProcessBuilder
* @since 1.3
*/
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);
}
/**
* Executes the specified command and arguments in a separate process.
*
* <p>This is a convenience method. An invocation of the form
* <tt>exec(cmdarray)</tt>
* behaves in exactly the same way as the invocation
* <tt>{@link #exec(String[], String[], File) exec}(cmdarray, null, null)</tt>.
*
* @param cmdarray array containing the command to call and
* its arguments.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>cmdarray</code> is <code>null</code>,
* or one of the elements of <code>cmdarray</code> is <code>null</code>
*
* @throws IndexOutOfBoundsException
* If <code>cmdarray</code> is an empty array
* (has length <code>0</code>)
*
* @see ProcessBuilder
*/
public Process exec(String cmdarray[]) throws IOException {
return exec(cmdarray, null, null);
}
/**
* Executes the specified command and arguments in a separate process
* with the specified environment.
*
* <p>This is a convenience method. An invocation of the form
* <tt>exec(cmdarray, envp)</tt>
* behaves in exactly the same way as the invocation
* <tt>{@link #exec(String[], String[], File) exec}(cmdarray, envp, null)</tt>.
*
* @param cmdarray array containing the command to call and
* its arguments.
*
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* <tt>null</tt> if the subprocess should inherit
* the environment of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>cmdarray</code> is <code>null</code>,
* or one of the elements of <code>cmdarray</code> is <code>null</code>,
* or one of the elements of <code>envp</code> is <code>null</code>
*
* @throws IndexOutOfBoundsException
* If <code>cmdarray</code> is an empty array
* (has length <code>0</code>)
*
* @see ProcessBuilder
*/
public Process exec(String[] cmdarray, String[] envp) throws IOException {
return exec(cmdarray, envp, null);
}
/**
* Executes the specified command and arguments in a separate process with
* the specified environment and working directory.
*
* <p>Given an array of strings <code>cmdarray</code>, representing the
* tokens of a command line, and an array of strings <code>envp</code>,
* representing "environment" variable settings, this method creates
* a new process in which to execute the specified command.
*
* <p>This method checks that <code>cmdarray</code> is a valid operating
* system command. Which commands are valid is system-dependent,
* but at the very least the command must be a non-empty list of
* non-null strings.
*
* <p>If <tt>envp</tt> is <tt>null</tt>, the subprocess inherits the
* environment settings of the current process.
*
* <p>A minimal set of system dependent environment variables may
* be required to start a process on some operating systems.
* As a result, the subprocess may inherit additional environment variable
* settings beyond those in the specified environment.
*
* <p>{@link ProcessBuilder#start()} is now the preferred way to
* start a process with a modified environment.
*
* <p>The working directory of the new subprocess is specified by <tt>dir</tt>.
* If <tt>dir</tt> is <tt>null</tt>, the subprocess inherits the
* current working directory of the current process.
*
* <p>If a security manager exists, its
* {@link SecurityManager#checkExec checkExec}
* method is invoked with the first component of the array
* <code>cmdarray</code> as its argument. This may result in a
* {@link SecurityException} being thrown.
*
* <p>Starting an operating system process is highly system-dependent.
* Among the many things that can go wrong are:
* <ul>
* <li>The operating system program file was not found.
* <li>Access to the program file was denied.
* <li>The working directory does not exist.
* </ul>
*
* <p>In such cases an exception will be thrown. The exact nature
* of the exception is system-dependent, but it will always be a
* subclass of {@link IOException}.
*
*
* @param cmdarray array containing the command to call and
* its arguments.
*
* @param envp array of strings, each element of which
* has environment variable settings in the format
* <i>name</i>=<i>value</i>, or
* <tt>null</tt> if the subprocess should inherit
* the environment of the current process.
*
* @param dir the working directory of the subprocess, or
* <tt>null</tt> if the subprocess should inherit
* the working directory of the current process.
*
* @return A new {@link Process} object for managing the subprocess
*
* @throws SecurityException
* If a security manager exists and its
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
* @throws IOException
* If an I/O error occurs
*
* @throws NullPointerException
* If <code>cmdarray</code> is <code>null</code>,
* or one of the elements of <code>cmdarray</code> is <code>null</code>,
* or one of the elements of <code>envp</code> is <code>null</code>
*
* @throws IndexOutOfBoundsException
* If <code>cmdarray</code> is an empty array
* (has length <code>0</code>)
*
* @see ProcessBuilder
* @since 1.3
*/
public Process exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}
/**
* Returns the number of processors available to the Java virtual machine.
*
* <p> This value may change during a particular invocation of the virtual
* machine. Applications that are sensitive to the number of available
* processors should therefore occasionally poll this property and adjust
* their resource usage appropriately. </p>
*
* @return the maximum number of processors available to the virtual
* machine; never smaller than one
* @since 1.4
*/
public native int availableProcessors();
/**
* Returns the amount of free memory in the Java Virtual Machine.
* Calling the
* <code>gc</code> method may result in increasing the value returned
* by <code>freeMemory.</code>
*
* @return an approximation to the total amount of memory currently
* available for future allocated objects, measured in bytes.
*/
public native long freeMemory();
/**
* Returns the total amount of memory in the Java virtual machine.
* The value returned by this method may vary over time, depending on
* the host environment.
* <p>
* Note that the amount of memory required to hold an object of any
* given type may be implementation-dependent.
*
* @return the total amount of memory currently available for current
* and future objects, measured in bytes.
*/
public native long totalMemory();
/**
* Returns the maximum amount of memory that the Java virtual machine will
* attempt to use. If there is no inherent limit then the value {@link
* java.lang.Long#MAX_VALUE} will be returned.
*
* @return the maximum amount of memory that the virtual machine will
* attempt to use, measured in bytes
* @since 1.4
*/
public native long maxMemory();
/**
* Runs the garbage collector.
* Calling this method suggests that the Java virtual machine expend
* effort toward recycling unused objects in order to make the memory
* they currently occupy available for quick reuse. When control
* returns from the method call, the virtual machine has made
* its best effort to recycle all discarded objects.
* <p>
* The name <code>gc</code> stands for "garbage
* collector". The virtual machine performs this recycling
* process automatically as needed, in a separate thread, even if the
* <code>gc</code> method is not invoked explicitly.
* <p>
* The method {@link System#gc()} is the conventional and convenient
* means of invoking this method.
*/
public native void gc();
/* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
private static native void runFinalization0();
/**
* Runs the finalization methods of any objects pending finalization.
* Calling this method suggests that the Java virtual machine expend
* effort toward running the <code>finalize</code> methods of objects
* that have been found to be discarded but whose <code>finalize</code>
* methods have not yet been run. When control returns from the
* method call, the virtual machine has made a best effort to
* complete all outstanding finalizations.
* <p>
* The virtual machine performs the finalization process
* automatically as needed, in a separate thread, if the
* <code>runFinalization</code> method is not invoked explicitly.
* <p>
* The method {@link System#runFinalization()} is the conventional
* and convenient means of invoking this method.
*
* @see java.lang.Object#finalize()
*/
public void runFinalization() {
runFinalization0();
}
/**
* Enables/Disables tracing of instructions.
* If the <code>boolean</code> argument is <code>true</code>, this
* method suggests that the Java virtual machine emit debugging
* information for each instruction in the virtual machine as it
* is executed. The format of this information, and the file or other
* output stream to which it is emitted, depends on the host environment.
* The virtual machine may ignore this request if it does not support
* this feature. The destination of the trace output is system
* dependent.
* <p>
* If the <code>boolean</code> argument is <code>false</code>, this
* method causes the virtual machine to stop performing the
* detailed instruction trace it is performing.
*
* @param on <code>true</code> to enable instruction tracing;
* <code>false</code> to disable this feature.
*/
public native void traceInstructions(boolean on);
/**
* Enables/Disables tracing of method calls.
* If the <code>boolean</code> argument is <code>true</code>, this
* method suggests that the Java virtual machine emit debugging
* information for each method in the virtual machine as it is
* called. The format of this information, and the file or other output
* stream to which it is emitted, depends on the host environment. The
* virtual machine may ignore this request if it does not support
* this feature.
* <p>
* Calling this method with argument false suggests that the
* virtual machine cease emitting per-call debugging information.
*
* @param on <code>true</code> to enable instruction tracing;
* <code>false</code> to disable this feature.
*/
public native void traceMethodCalls(boolean on);
/**
* Loads the native library specified by the filename argument. The filename
* argument must be an absolute path name.
* (for example
* <code>Runtime.getRuntime().load("/home/avh/lib/libX11.so");</code>).
*
* If the filename argument, when stripped of any platform-specific library
* prefix, path, and file extension, indicates a library whose name is,
* for example, L, and a native library called L is statically linked
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the file
* system. See the JNI Specification for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
* <p>
* First, if there is a security manager, its <code>checkLink</code>
* method is called with the <code>filename</code> as its argument.
* This may result in a security exception.
* <p>
* This is similar to the method {@link #loadLibrary(String)}, but it
* accepts a general file name as an argument rather than just a library
* name, allowing any file of native code to be loaded.
* <p>
* The method {@link System#load(String)} is the conventional and
* convenient means of invoking this method.
*
* @param filename the file to load.
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
* @exception UnsatisfiedLinkError if either the filename is not an
* absolute path name, the native library is not statically
* linked with the VM, or the library cannot be mapped to
* a native library image by the host system.
* @exception NullPointerException if <code>filename</code> is
* <code>null</code>
* @see java.lang.Runtime#getRuntime()
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
@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);
}
/**
* Loads the native library specified by the <code>libname</code>
* argument. The <code>libname</code> argument must not contain any platform
* specific prefix, file extension or path. If a native library
* called <code>libname</code> is statically linked with the VM, then the
* JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
* See the JNI Specification for more details.
*
* Otherwise, the libname argument is loaded from a system library
* location and mapped to a native library image in an implementation-
* dependent manner.
* <p>
* First, if there is a security manager, its <code>checkLink</code>
* method is called with the <code>libname</code> as its argument.
* This may result in a security exception.
* <p>
* The method {@link System#loadLibrary(String)} is the conventional
* and convenient means of invoking this method. If native
* methods are to be used in the implementation of a class, a standard
* strategy is to put the native code in a library file (call it
* <code>LibFile</code>) and then to put a static initializer:
* <blockquote><pre>
* static { System.loadLibrary("LibFile"); }
* </pre></blockquote>
* within the class declaration. When the class is loaded and
* initialized, the necessary native code implementation for the native
* methods will then be loaded as well.
* <p>
* If this method is called more than once with the same library
* name, the second and subsequent calls are ignored.
*
* @param libname the name of the library.
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
* @exception UnsatisfiedLinkError if either the libname argument
* contains a file path, the native library is not statically
* linked with the VM, or the library cannot be mapped to a
* native library image by the host system.
* @exception NullPointerException if <code>libname</code> is
* <code>null</code>
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
@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);
}
/**
* Creates a localized version of an input stream. This method takes
* an <code>InputStream</code> and returns an <code>InputStream</code>
* equivalent to the argument in all respects except that it is
* localized: as characters in the local character set are read from
* the stream, they are automatically converted from the local
* character set to Unicode.
* <p>
* If the argument is already a localized stream, it may be returned
* as the result.
*
* @param in InputStream to localize
* @return a localized input stream
* @see java.io.InputStream
* @see java.io.BufferedReader#BufferedReader(java.io.Reader)
* @see java.io.InputStreamReader#InputStreamReader(java.io.InputStream)
* @deprecated As of JDK 1.1, the preferred way to translate a byte
* stream in the local encoding into a character stream in Unicode is via
* the <code>InputStreamReader</code> and <code>BufferedReader</code>
* classes.
*/
@Deprecated
public InputStream getLocalizedInputStream(InputStream in) {
return in;
}
/**
* Creates a localized version of an output stream. This method
* takes an <code>OutputStream</code> and returns an
* <code>OutputStream</code> equivalent to the argument in all respects
* except that it is localized: as Unicode characters are written to
* the stream, they are automatically converted to the local
* character set.
* <p>
* If the argument is already a localized stream, it may be returned
* as the result.
*
* @deprecated As of JDK 1.1, the preferred way to translate a
* Unicode character stream into a byte stream in the local encoding is via
* the <code>OutputStreamWriter</code>, <code>BufferedWriter</code>, and
* <code>PrintWriter</code> classes.
*
* @param out OutputStream to localize
* @return a localized output stream
* @see java.io.OutputStream
* @see java.io.BufferedWriter#BufferedWriter(java.io.Writer)
* @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
* @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
*/
@Deprecated
public OutputStream getLocalizedOutputStream(OutputStream out) {
return out;
}
}
/*
* Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.lang;
import java.io.*;
import java.util.concurrent.TimeUnit;
/**
* The {@link ProcessBuilder#start()} and
* {@link Runtime#exec(String[],String[],File) Runtime.exec}
* methods create a native process and return an instance of a
* subclass of {@code Process} that can be used to control the process
* and obtain information about it. The class {@code Process}
* provides methods for performing input from the process, performing
* output to the process, waiting for the process to complete,
* checking the exit status of the process, and destroying (killing)
* the process.
*
* <p>The methods that create processes may not work well for special
* processes on certain native platforms, such as native windowing
* processes, daemon processes, Win16/DOS processes on Microsoft
* Windows, or shell scripts.
*
* <p>By default, the created subprocess does not have its own terminal
* or console. All its standard I/O (i.e. stdin, stdout, stderr)
* operations will be redirected to the parent process, where they can
* be accessed via the streams obtained using the methods
* {@link #getOutputStream()},
* {@link #getInputStream()}, and
* {@link #getErrorStream()}.
* The parent process uses these streams to feed input to and get output
* from the subprocess. Because some native platforms only provide
* limited buffer size for standard input and output streams, failure
* to promptly write the input stream or read the output stream of
* the subprocess may cause the subprocess to block, or even deadlock.
*
* <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
* subprocess I/O can also be redirected</a>
* using methods of the {@link ProcessBuilder} class.
*
* <p>The subprocess is not killed when there are no more references to
* the {@code Process} object, but rather the subprocess
* continues executing asynchronously.
*
* <p>There is no requirement that a process represented by a {@code
* Process} object execute asynchronously or concurrently with respect
* to the Java process that owns the {@code Process} object.
*
* <p>As of 1.5, {@link ProcessBuilder#start()} is the preferred way
* to create a {@code Process}.
*
* @since JDK1.0
*/
public abstract class Process {
/**
* Returns the output stream connected to the normal input of the
* subprocess. Output to the stream is piped into the standard
* input of the process represented by this {@code Process} object.
*
* <p>If the standard input of the subprocess has been redirected using
* {@link ProcessBuilder#redirectInput(Redirect)
* ProcessBuilder.redirectInput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
*
* <p>Implementation note: It is a good idea for the returned
* output stream to be buffered.
*
* @return the output stream connected to the normal input of the
* subprocess
*/
public abstract OutputStream getOutputStream();
/**
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* output of the process represented by this {@code Process} object.
*
* <p>If the standard output of the subprocess has been redirected using
* {@link ProcessBuilder#redirectOutput(Redirect)
* ProcessBuilder.redirectOutput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Otherwise, if the standard error of the subprocess has been
* redirected using
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then the input stream returned by this method will receive the
* merged standard output and the standard error of the subprocess.
*
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
*
* @return the input stream connected to the normal output of the
* subprocess
*/
public abstract InputStream getInputStream();
/**
* Returns the input stream connected to the error output of the
* subprocess. The stream obtains data piped from the error output
* of the process represented by this {@code Process} object.
*
* <p>If the standard error of the subprocess has been redirected using
* {@link ProcessBuilder#redirectError(Redirect)
* ProcessBuilder.redirectError} or
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
*
* @return the input stream connected to the error output of
* the subprocess
*/
public abstract InputStream getErrorStream();
/**
* Causes the current thread to wait, if necessary, until the
* process represented by this {@code Process} object has
* terminated. This method returns immediately if the subprocess
* has already terminated. If the subprocess has not yet
* terminated, the calling thread will be blocked until the
* subprocess exits.
*
* @return the exit value of the subprocess represented by this
* {@code Process} object. By convention, the value
* {@code 0} indicates normal termination.
* @throws InterruptedException if the current thread is
* {@linkplain Thread#interrupt() interrupted} by another
* thread while it is waiting, then the wait is ended and
* an {@link InterruptedException} is thrown.
*/
public abstract int waitFor() throws InterruptedException;
/**
* Causes the current thread to wait, if necessary, until the
* subprocess represented by this {@code Process} object has
* terminated, or the specified waiting time elapses.
*
* <p>If the subprocess has already terminated then this method returns
* immediately with the value {@code true}. If the process has not
* terminated and the timeout value is less than, or equal to, zero, then
* this method returns immediately with the value {@code false}.
*
* <p>The default implementation of this methods polls the {@code exitValue}
* to check if the process has terminated. Concrete implementations of this
* class are strongly encouraged to override this method with a more
* efficient implementation.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the {@code timeout} argument
* @return {@code true} if the subprocess has exited and {@code false} if
* the waiting time elapsed before the subprocess has exited.
* @throws InterruptedException if the current thread is interrupted
* while waiting.
* @throws NullPointerException if unit is null
* @since 1.8
*/
public boolean waitFor(long timeout, TimeUnit unit)
throws InterruptedException
{
long startTime = System.nanoTime();
long rem = unit.toNanos(timeout);
do {
try {
exitValue();
return true;
} catch(IllegalThreadStateException ex) {
if (rem > 0)
Thread.sleep(
Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
}
rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
} while (rem > 0);
return false;
}
/**
* Returns the exit value for the subprocess.
*
* @return the exit value of the subprocess represented by this
* {@code Process} object. By convention, the value
* {@code 0} indicates normal termination.
* @throws IllegalThreadStateException if the subprocess represented
* by this {@code Process} object has not yet terminated
*/
public abstract int exitValue();
/**
* Kills the subprocess. Whether the subprocess represented by this
* {@code Process} object is forcibly terminated or not is
* implementation dependent.
*/
public abstract void destroy();
/**
* Kills the subprocess. The subprocess represented by this
* {@code Process} object is forcibly terminated.
*
* <p>The default implementation of this method invokes {@link #destroy}
* and so may not forcibly terminate the process. Concrete implementations
* of this class are strongly encouraged to override this method with a
* compliant implementation. Invoking this method on {@code Process}
* objects returned by {@link ProcessBuilder#start} and
* {@link Runtime#exec} will forcibly terminate the process.
*
* <p>Note: The subprocess may not terminate immediately.
* i.e. {@code isAlive()} may return true for a brief period
* after {@code destroyForcibly()} is called. This method
* may be chained to {@code waitFor()} if needed.
*
* @return the {@code Process} object representing the
* subprocess to be forcibly destroyed.
* @since 1.8
*/
public Process destroyForcibly() {
destroy();
return this;
}
/**
* Tests whether the subprocess represented by this {@code Process} is
* alive.
*
* @return {@code true} if the subprocess represented by this
* {@code Process} object has not yet terminated.
* @since 1.8
*/
public boolean isAlive() {
try {
exitValue();
return false;
} catch(IllegalThreadStateException e) {
return true;
}
}
}
转载自:https://blog.csdn.net/dongliheng/article/details/1684628
更多推荐
所有评论(0)