World Map
Java Service Wrapper is the easiest way to make your product more reliable.
  • Free Trial
  • Buy Now
Wrapper Native Exec

Wrapper Native Execute Overview

Overview

The WrapperManager.exec() function is an alternative to the Java-Runtime.exec() or Java-ProcessBuilder which has the disadvantage to use the fork() method, which can become on some platforms very memory expensive to create a new process. The problem on those platforms is, that in the Parent Process which wants to start a side process, fork() causes to clone the memory heap of the parent for the child. This will double the used memory for a short time. Given a fairly large application which is close to the systems memory quota, it might fail to just create a small application like ls, or the memory is going to get swapped on the HD, which decreases the performance drastically.

Another issue is to ease bind or detach the child while starting from the parent. If the Java Process terminates expectedly or unexpectedly, the Wrapper will clean all bind processes which haven't finished yet.

For better consistency, the WrapperManager.exec() function was implemented as close to the Runtime.exec() function in Java as possible.

Executing

Start

This section will start right away to show how to execute a command. (Further details will be explained step-by-step during reading this page)

WrapperProcess p = WrapperManager.exec("ls -lisa");

This command will execute an ls command with the parameters -l and -s. The representation on the Java side of the process is the returned WrapperProcess object.

If the full path of the binary (or script) file hasn't been passed, the current working directory as well as systems' PATH directories will be checked and the first found hit gets executed. Relative addressing starting from the current working directory is also supported.

NOTE

The exec command accepts the command either as a single String as well as a StringArray. In case of a StringArray, each parameter is located in an single array field.

File I/O

The created child process runs in the background of the OS and is usually not visible as long as it's not a GUI application. To communicate with the process, the WrapperProcess class provides three methods to access the Input to the process as well as the Output and the ErrorMessages to the process.

It is recommended to wrap the returned StreamObject with a BufferedReader. To open the Reader, please proceed as described.

BufferedReader br = new BufferedReader( new InputStreamReader(p.getWrapperProcessInputStream()));

This establishes the Reader of the InputStream on which the child writes its output. To read data from the ErrorStream or write data to the Child, please proceed similar to this example.

Once the Reader/Writer has been established, we can read/write data by:

String line;
while ((line = br.readLine()) != null)
{
    System.out.println(line);
}
br.close();

NOTE

Please note that by following this example all data will be read until the child process closes the stream on its side.

Configuration of the Child Process

When executing a command the WrapperManager also provides the possibility to configure the child process. This is done by passing a WrapperProcessConfig object to the exec() function. The following section will explain the Configurations which can be made by WrapperProcessConfiguration.

Detached Process

This field specifies whether the subprocess will be run "detached" from the Wrapper. If the process is marked as "detached", the process doesn't need to terminate when the Wrapper is shutting down. If not marked, the Wrapper will keep track of the child process and try to terminate the process if the parent process should terminate.

NOTE

By default, processes won't be started with detached from its parent process.

Start Type

This field specifies a Start Type of how the subprocess will be started by the OS.

WARNING

this property has no effect on Windows.

  • FORK_EXEC:

    This is the most common way in Linux/UNIX to create a child process. However on some OS (esp. Solaris), this call causes to initially duplicate the memory of the parent for the child. On z/OS, this Start Type is not supported as of the initial release. On HP-UX systems, the Wrapper will automatically switch to using vfork rather than fork().

  • VFORK_EXEC:

    The vfork() function differs from fork() only in that the child process can share code and data with the parent process. This speeds cloning activity significantly at a risk for the integrity of the parent process if vfork() is misused. On some systems, vfork is the same as fork. On z/OS, this Start Type is not supported as of the initial release.

  • POSIX_SPAWN:

    Process will be spawned and won't cause any memory duplication POSIX_SPAWN API This is only available on Linux, Solaris (10+), AIX, z/OS and MacOS.

  • DYNAMIC:

    The optimal Start Type will be automatically selected according to the OS the Wrapper is running on. Please note that this property also implies that changing the working directory will not be supported because of not supporting changing the working directory when using POSIX_SPAWN. There is an experimental property wrapper.child.allowCWDOnSpawn which could be used to achieve in changing the working directory.

NOTE

By default, processes will be launched using the Start Type DYNAMIC.

Working Directory

This field specifies the working directory of the subprocess, or "NULL" if the subprocess should inherit the working directory of the current process.

Please note, when using POSIX_SPAWN, it is not possible to set the working directory directly. A suggested work around would be to wrap the command you wish to run in a script and perform a change of directory prior to the execution of the command.

#!/bin/sh

chdir $1
shift
$*

NOTE

If this property is not set, the subprocess will inherit the working directory from its parent process.

wrapper.child.allowCWDOnSpawn

The wrapper.child.allowCWDOnSpawn property controls whether the Wrapper will try to change the working directory for the Start Type of POSIX_SPAWN and DYNAMIC.

This property is experimental and could lead to problems if the wrapped process is using Java Native Interface (JNI) Code and would try to create a child process using POSIX_SPAWN.

By default, this property is set to FALSE.

Wrapper.child.allowCWDOnSpawn=TRUE

Setting the Environment

This field specifies the environment of the created subprocess.

The field is an array of strings, each element of it has environment variable settings in format "name=value".

NOTE

If this property is not set, the subprocess will inherit the environment from its parent process.

Specifying a soft timeout for child termination

Since Wrapper version 3.5.5 it is also possible to specify a soft timeout for each process individually, the Wrapper will give the child process the chance to terminate by itself gracefully, whereas for instance the java.lang.Process.destroy() method will always cause a forced shutdown, giving the process no chance on shutting down by itself. Before Wrapper version 3.5.5, the timeout was always 5 sec, so in order to keep functionality consistent, the default value of timeout is 5 sec.

The timeout can be specified during the child process creation with the WrapperProcessConfig class.

WrapperProcessConfig wpConfig = new WrapperProcessConfig().setSoftShutdownTimeout(10);

The configuration in the above example will tell the Wrapper to wait for up to 10 seconds for any child process, which got created with that configuration. If the child processes doesn't finish after 10 seconds, the Wrapper will kill it forcibly.

The following values for a timeout are possible

  • >0:

    The amount of seconds the Wrapper wait at least for the child process to exit gracefully before forced termination.

  • 0:

    The Wrapper will instantly force the termination of the child process.

  • -1:

    The Wrapper will never force the termination of the child process, but wait indefinitely for the child process to finish by itself.

Creating Child Process for Active User

WrapperProcessConfig.setCreateForActiveUser(boolean) property, specifies if the ChildProcesses should be launched in the current active session rather than the session, the service is running.

This property only makes sense if the application was launched as Windows Service under the System User (or any other user, having SE_TCB_NAME privilege with the OS) On non-Windows platforms or when launched in Console mode, the setting will be ignored silently.

By default, this property is set to FALSE.