Container Services

For a listing of bug fixes and enhancements included in this release, please visit our bug database.

The purpose of the Openwings container implementation is to allow multiple Java process to be run inside the same JVM. There are several goals that we aimed to achieve with our implementation:

  • Reduce the footprint of an Openwings system by running fewer JVMs. Core Java classes (java.*, javax.*, etc.) are shared between processes.
  • Processes running inside a container (shared JVM) should be completely isolated from each other and not able to affect each other.
  • Any legal Java process should run successfully without modification inside the container (Note: this is different than a J2EE environment where EJBs cannot perform certain functions like threading).

Our implementation is mostly successful in acheiving these goals. However, since the Java language does not have a proper process abstraction to date, there are some caveats, as well as behaviors we've had to limit.

In the meantime, we've had a large degree of success in our container implementation. We've been successful in isolating processes in several key aspects:

  • Thread management. Each process is executed in its own ThreadGroup and may not access threads from another process. When a process stops, its threads are cleaned up.
  • Class scope. Each process is isolated in its own ClassLoader.
  • AWT/Swing. Processes can open and close windows freely. If a process stops without closing a window, the container detects this and cleans up the process window.
  • Property access. Each process has its own set of system properties.
  • Security policy. Each process has its own security policy applied to it.
  • Exit. System.exit() and Runtime.exit() are trapped so that when a process calls these methods, it is stopped without shutting down the entire JVM.
  • Output. The System.err and System.out streams have been replaced so that the output of each process is redirected to a separate log file.

There are practical reasons for not running some Java processes in the Openwings container reference implementation. Here is a summary of known weaknesses of the container implementation:

  • Memory usage. The JVM is being run with a memory limit. If one process uses up all the memory, other processes will get OutOfMemoryErrors. There is no way to partition or allocate the memory of the JVM between different processes.
  • CPU usage. If a process in the container goes into an infinite loop, it can lock out other processes in the container. There is no way to monitor the CPU usage of a particular process within a container. A possible mitigation would be to lower the priority of a process's root thread group, although we have not explored this yet.

We've also had to limit certain functions that would be allowed to a regular Java program:

  • System.setSecurityManager(). This will always result in a SecurityException. The container has a single security manager that may not be replaced.
  • System.setProperties()/getProperties(). This will always result in a SecurityException. The container has a single properties object that may not be replaced. However, system properties are isolated between processes, and System.setProperty()/getProperty() is allowed.
  • System.setOut()/System.setErr(). This will always result in a SecurityException. The container controls where the output of each process goes.
  • Thread(). This is one of the most intricate parts of the container implementation. Using methods such as Thread.getThreadGroup(), ThreadGroup.getParent(), ThreadGroup.enumerate(), it is possible to navigate the entire thread model of a JVM. We have decided to allow processes to only create and access threads in their own thread groups.

The threading limitations deserve a fuller explanation, especially since they are new in the 0.9.2 release.

Everyone would agree that processes in a container should not be allowed to access the threads and thread groups of other processes, or the threads used to manage the container itself. What is more controversial is our decision to protect access to thread access and creation in the JVM's core thread groups. This includes the JVM thread groups called "main"/"system", "AWT" and "RMI". By default, process code may not create threads in these thread groups (note that threads created by Java core libraries are generally allowed). However, there are legitimate reasons that processes would want to create threads in these groups, so we provide a configurable permission to allow trusted code to create threads in these core JVM thread groups.

To allow code access to the core JVM thread groups, you will need to grant the following permission:

permission com.gd.openwings.container.jvm.ContainerThreadPermission, "<thread group name>";

The "ContainerThreadPermission" class extends java.security.BasicPermission, so the thread group name may be wildcarded.

This permission should be granted with caution. For example, if a process were allowed to create threads in the system thread group, it could create a long running thread that would not be identified as being part of the process and could therefore outlive the process. Here's another example: if a process were allowed to get an enumeration of the threads in the AWT thread group, it could attack the windowing for all processes in the container.

The most common cases where programmers will run into this problem is when applications create worker threads in callbacks:

Threading example 1 - RMI: An application provides a service and has used an RMI connector. On an incoming RMI call, the application spawns a thread to perform some task. If this thread is created using the Thread() constructor, a SecurityException will be thrown, since the Thread() constructor defaults to creating the thread in the current thread group. Since this is an incoming RMI call, the current thread group is the RMI thread group, which the process is not allowed to access. The workaround is for the application to save off its root thread group during startup (Thread.currentThread().getThreadGroup()). When an incoming RMI call is received, the application should create the worker thread using the Thread(ThreadGroup, String) constructor, passing in the process thread group.

Threading example 2 - AWT/Swing: An application displays a window with a button or some other widget that has a callback. In the context of the callback, the application spawns a thread to perform some task. If this thread is created using the Thread() constructor, a SecurityException will be thrown -- the current thread group is the AWT thread group. The workaround described above in the RMI example is useful, also consider using SwingUtilities.invokeLater(Runnable) for Swing apps.

Feature History

  • 1.1
    • Fixed defect 6766 (java.exe crashes on Windows). This was a major reliability problem on Windows platforms that occurred periodically when stopping a process running in a container.
    • Added new permission com.gd.openwings.container.jvm.ContainerThreadPermission to allow access to core JVM threads.
  • 1.0
    • No new features
  • 0.9.2
    • Container Manager (ow)
      • Clean shutdown for standalone Java programs
    • Container
      • Code Security - enforcement of per-process Java security policies
    • LogAccess utility
      • View process log files remotely, even for stopped processes
  • 0.9.1
    • Container Manager (ow)
      • Support for platform-specific performance monitors, including Solaris/SunOS, Linux, Windows
    • Container
      • Significant performance/reliability improvements from 0.9 release
    • LogAccess utility
      • Customizable control of log files - turn logging off entirely, limit log file size, or schedule automatic deletion of log files
  • 0.9
    • Container Manager (ow)
      • Improved support for components that use native code
      • Remote access to process log files through the Openwings Explorer
  • 0.8.x
    • Container Manager (ow)
      • Manages execution of Java and non-Java programs
      • Manages containers on a single platform
      • Restart and Fail-Over Support
      • Automatically runs core services
    • Container
      • Supports Java virtual machine sharing
      • Supports Mobile applications

Known Issues

  • Container Manager (ow)
    • There is no implementation of clustering in this release.
  • Container
    • The fix for defect 6766 (java.exe crashes) may result in a small number of process threads outliving the process (specifically, threads that are on a wait() call may not exit).
    • Running a Java component that creates GUIs or registers a shutdown hook makes the component uninstallable until Openwings is restarted. This is a Java bug.
    • Starting and stopping components produces a slow memory leak in the Container, due to classes not being unloaded. This is a Java bug.

Future Releases

  • Clustering support

back to top

© Copyright 2003, General Dynamics Decision Systems. All rights reserved.