Java Operating Systems: Design and Implementation
Godmar Back, Pat Tullmann, Leigh Stoller, Wilson Hseih, Jay Lepreau (Utah), 1998
Summary. A process abstraction is necessary in language-based
OSes that enables resource management and interprocess communication --
not just protection. A spectrum of challenges exist in resource mgt of
cycles, memory and network bandwidth. The authors list several issues
and describe solutions from three sample systems: GVM, Alta and JKernel.
More Detail.
Memory. Two issues:
- Sharing model: copying, direct, indirect (direct with
an additional level of indirection). These vary
indirectly in performance and ease-of-protection.
- Allocation. Straightforward approach: JVM debits process
on allocation; GC system credits on cleanup. Fragmentation
attack: when a process with a small budget allocates small
chunks in a system which only allocates by large chunk.
- GVM. Use separate heaps. Disallow cross-heap
refs. Shared objects allocated
in special system heap. Can do process->sys/sys->process refs. GC
strategy explained but not groked.
- Alta. Java microkernel. Nested process model. Inter-process sharing
via sockets. Cross-process refs provided via capabilities for
siblings *if* they share the same class namespace view and the
shared classes are final.
Parents must make sure that cross-process refs are not
created if full memory reclamation is required upon
termination. Memory allocation won't fail in system code
because allocation done before entering "system code".
System call entry/exit explicit (?).
- JKernel. Java microkernel. Support multiple
protection domains called tasks. Class loaders used to give tasks their
own namespace. Communication based on revokable capabilities;
supports thread migration (full context switch not required)
between tasks but not cross-task communication. Does bytecode
rewriting to check for memory credits; precision limited because
authors use stock JVM (no rewriting there).
CPU Usage. Two mechanisms must be in place to manage cycles:
- Accounting:
- Non-shared services implemented as library or system calls
easy: acctg amounts to counting CPU time thread accrues.
- GC.Shared system services such as GC complicate;if
treated as a global service, two types of attacks possible:
GC denial-of-service attack possible if a malicious process
continually causes invocation of GC; priority inversion can
also occur if a lower priority process causes invocation of GC
such that higher priority process cannot run. Two GC approaches:
ould do GC acctg as global service but charge each block to
appropriate process; probably too costly. Second approach: per-process
heap.
- Packet Handling. Goal is to minimize time to
demux so that resources can be charged. Authors advocate LRP -
a combination
of early demuxing, early packet discard, and processing of
packets at the receiver's priority.
- Preemptibility: challenge is to avoid causing priority
inversion
or deadlock by preempting or killing low-priority thread holding
a shared lock. Java systems must define a user/kernel boundary.
- GVM. Combines traditional Java thread group hierarchy
with CPU inheritance scheduling. Scheduler hierarchies can be built.
At the root group, fixed priority scheduler provided so that
system heap GC thread has highest priority. At the next level,
stride scheduling amongst processes.
- Alta. CPU inheritance scheduling. GC as a system
service so open to GC denial-of-service attack.
- JKernel. Monitor CPU time consumed by thread;
reactive - can't prevent thread from crossing limit, only
prevent it from using more once limit crossed.
Network bandwidth. Can count packets by process, socket, session.
Must be careful of the level in which resource acctg is done: high level
acctg may not reflect physical resources accurately.
- GVM. H-PFQ: allows packet schedulers to be stacked
in a scheduling hierarchy.
- Alta. No support.
- JKernel. Uses a custom WinSock DLL that counts the
number of bytes transmitted by a particular socket.