Chapter 6
Related Work

Alta touches on a large body of related work in two specific areas: java-based operating systems research and more general operating systems research.

6.1 Related Java work

There are currently six other Java-based projects that provide OS-style support for Java applications in a single virtual machine: the J-Kernel, KaffeOS, the Princeton JVM, Conversant, Sun's JavaOS, and the E-Communities capability system.

6.1.1 The J-Kernel

The J-Kernel [29] from Cornell is implemented entirely in Java and requires no changes or enhancements to the virtual machine. The J-Kernel concentrates on clean domain termination and provides this by enforcing complete separation of processes, even between domains that have some degree of trust between them. As pointed out by the J-Kernel authors, the "main problem with the approach taken in the J-Kernel is that data structures cannot be shared directly among tasks, thus not realizing one of the major potential gains of a language-based protection model" [30]. Additionally, the J-Kernel's cross-domain thread migration does not provide true separation, as a thread can block in another domain, out of reach of the owning domain. This model is sufficient for environments similar to applet environments, where the callee is trusted by the caller.

The J-Kernel uses on-the-fly LRMI stub generation to guarantee that no object references are passed between two domains. The stubs transparently convert any implicit cross-domain references into capabilities. The generated capabilities provide an indirect level of access to remote objects and insure memory separation for processes. Alta, on the other hand, allows two processes to share object references directly. Alta could use the J-Kernel's dynamic stub generator to transparently create IPC-based remote object interfaces for Java objects. Currently Alta's IPCIF interfaces are written by hand.

Because the J-Kernel has been restricted to an unmodified virtual machine, the support for control over memory and CPU usage is cumbersome or ineffective. CPU scheduling is done indirectly by manipulating thread priorities based on CPU usage. Memory accounting only takes into account memory directly used by Java-level objects; structures which are internal to the virtual machine are not charged to the owning process. The pure Java approach used to implement the J-Kernel allows it to take advantage of the best available Java virtual machine. Of course, resource management in the J-Kernel would easily benefit from providing direct virtual machine support as is done for Alta.

6.1.2 KaffeOS

KaffeOS is another Kaffe-based multiprocessing Java virtual machine from the University of Utah [6]. KaffeOS separates each Java process's heap and supports independent garbage collection of each heap. KaffeOS builds its notion of a process on top of Classloaders. Like Alta, KaffeOS will also support CPU inheritance scheduling for CPU management. KaffeOS has an even more restrictive form of interprocess sharing than Alta--the only mutable data that can be shared is primitive types. KaffeOS uses run-time write-barriers to prevent interheap references between processes. KaffeOS required no changes to the Java type system to support its sharing and communication mechanism.

Because KaffeOS is built on the same foundation as Alta, incorporating many of the engineering improvements--including garbage-collectible classes and CPU inheritance scheduling--from KaffeOS into Alta should be straightforward. On the other hand, reconciling the different process models and the different approaches to sharing might prove to be more difficult. For example, KaffeOS's per-process garbage collection relies on KaffeOS's restricted sharing model to avoid cross-process object references.

6.1.3 Princeton Multiprocessing JVM

Balfanz and Gong [7] describe a multiprocessing JVM developed to explore the security architecture ramifications of protecting applications from each other, as opposed to Sun's focus of only protecting the system from applications. They identify several areas of JDK version 1.2 that assume a single-application model, and propose extensions to allow multiple applications and to provide interapplication security. The focus of their multi-processing JVM is to explore the applicability of the JDK 1.2 security model to multiprocessing, and they rely on the existing, limited JDK infrastructure for resource control.

6.1.4 Conversant

A now defunct project from the Open Group Research Institute, Conversant [8] used a modified a Java virtual machine--running on Mach [1]--to support multiple Java processes. In Conversant, each Java process is provided with a separate, contiguous range of the virtual machine's address space, and a separate garbage collection thread. Conversant uses the extreme approach of total separation of processes within the virtual machine. Complete separation maximizes the effectiveness of resource accounting and control as all resource usage is trivially charged to the owning process. Conversant cannot, however, support any sharing between processes, and thus foregoes one of the major motivations for a type-safe-language based system.

6.1.5 JavaOS

Sun's JavaOS [43] was originally a complete platform written almost entirely in Java. It was described as a first-class OS for Java applications. From the scant literature available, JavaOS appears to provide a single Java virtual machine with no notion of a process or the ability to run multiple applications on that virtual machine. Sun Microsystems is replacing JavaOS with a new set of "Java operating systems": "JavaOS for Business," which only runs a single Java application; and "JavaOS for Consumers," which is built on the Chorus microkernel OS [37] to provide the real-time guarantees needed in embedded systems. Both of these systems require a separate virtual machine for each Java application, which results in unnecessary overhead for duplication of virtual machine structures and initialization.

6.1.6 E-Communities capability system

Electronic Communities' E extends Java with a capability-based framework for distributed computing. E targets distributed Java systems (distributed across multiple physical hosts), but many of the specified capabilities would be useful on the local system. E's capabilities are static--they are granted at object load time--and E has no notion of a "process" or any other unit of resource control. E does provide significant infrastructure useful for distributed Java applications, such as digital signatures. Alta focuses on safety and resource control on the local node.

6.2 Related work in operating systems

Many research operating systems have used software protection mechanisms. Some, such as Pilot, use software-based protection throughout the system. Others, such as SPIN, use software-based protection only for kernel extensions.

6.2.1 Fluke

Fluke is a microkernel that only uses hardware protection mechanisms for process separation. The nested process model was first implemented in Fluke and much of Fluke's implementation served as a blueprint for Alta's implementation. Fluke was described in detail in section 2.2 and compared to Alta in section 4.4.

6.2.2 Language-based operating systems

Pilot and Cedar

Pilot [36] and Cedar [44] are two of the earliest language-based operating systems. The whole of these systems (including user tools, OS internals, etc) was written in the Cedar language. All processes operated in a single address space. Because Cedar and Pilot were designed for single-user workstations, isolation of malicious or erroneous processes was not a goal and remained unenforceable. While the Cedar language provided many safety properties, the system did not prevent resource hoarding or the corruption of system data by malicious processes. Additionally, the language supported a set of "unsafe" features that were used in the lowest levels of the system to circumvent many of the language's safety properties. In a Java system these "unsafe" features are written in C and are unavailable in the language itself.

Oberon and Juice

The Oberon language and operating system [53] shares many of Java's features, although it is a nonpreemptive, single-threaded system. The designers assumed that all operations undertaken on Oberon would be inherently short and they assumed any compute-intensive work would be offloaded to a compute server. These assumptions were valid when this system was designed in the mid-1980s. Background tasks such as the garbage collector are implemented as consecutive calls to procedures, where "interruption" can only occur between top-level procedure calls (called commands in Oberon). All state for these background tasks is global. While protection between tasks is enforced by the language, the exposure of global state to all top-level procedure calls and the uninterruptibility of commands mean that isolation of tasks is not enforceable.

The Juice project [24] uses Oberon and Slim Binaries [25] to provide a Java-like environment for downloaded code. Juice is the conceptual equivalent of a Java virtual machine, except that it does not interpret bytecodes--Juice expects binaries in the Slim Binary format, which are converted to native code and executed directly. Juice improves the distribution of platform independent binaries in two ways. First, by distributing a form closer to a compiler-generated parse tree, Juice binaries, unlike Java bytecodes, do not need to be verified. Second, Juice binaries provide a more compact representation of a program than Java class files. Unlike Alta, Juice does not address resource consumption or accounting.

Inferno

Inferno [17] is a system developed at Bell Laboratories. Inferno consists of the Limbo programming language and the Dis virtual machine. Limbo and Dis provide type safety and verification facilities similar to Java's. Inferno is oriented to network applications and provides data streaming and strong networking support. Inferno uses an extended file system namespace to provide applications with resources (similar to Plan 9 [35]) and uses namespace controls to restrict application access to those resources. Inferno does not support memory controls and does not appear to maintain a clear distinction between application and kernel.

NewtonOS

NewtonOS [50] is an operating system that supports communication and synchronization between processes within a single address space. Applications are written in the NewtonScript scripting language. Because NewtonScript supports pointers, the CPU's paging hardware must be used to provide protection between processes. The system, however, was only designed to run highly cooperative processes that are mutually trusting. Under these assumptions interprocess protections are not strictly necessary.

SPIN

SPIN [9] is an extensible operating system kernel that lets users load and link extensions, written in Modula-3, into the kernel. These extensions can interact tightly with the kernel or other kernel extensions to perform virtual memory operations, application-specific disk access, or other system-level functions. Unlike Cedar, SPIN provides sufficient protection to allow untrusted modules but has no strict resource controls. The language, with assistance from the linker, keeps extensions from interfering with each other and from interfering with critical parts of the kernel. To maintain control over extensions SPIN adds features to the language, such as ephemeral procedures--in this case, to maintain preemptibility of an extension.

SPIN uses software-based protection only for kernel extensions; regular processes are managed with traditional hardware-based techniques. SPIN was designed and optimized to provide a very rich interface to kernel extensions and does not provide a general operating system interface for user mode processes. There is no notion of "process" within the kernel and thus no interprocess communication or process management. SPIN does not limit the memory resources of kernel extensions and the only CPU management supported is termination of "ephemeral" extensions that have exhausted their CPU allocation.

Vino

VINO is a software-based (but not language-based) extensible system [38] that addresses some of the resource control issues raised by SPIN by wrapping kernel extensions within transactions. When an extension exceeds its resource limits, it can be safely aborted (even if it holds kernel locks), and its resources can be recovered. Extensions, and the resources used by an extension, are shared equally among all users; extensions do not run under the identity of the user code they are executing on behalf of.

Like SPIN, VINO only uses software-based protection for managing kernel extensions. Regular user-mode processes are managed with traditional hardware-based page protections.