Virtualizing Java

Let us now discuss the implications of running an industrial strength Java application server in a virtualized environment. Consider the following figure that illustrates the entire stack from the application server down to the hardware. Between the Java application and the hardware on which it ultimately executes, we have a JVM, a general purpose OS (for example Oracle Enterprise Linux), and a Hypervisor (such as Oracle VM).

Virtualizing Java

The application server, for example Oracle WebLogic, is a typical Java application that needs a JVM to execute. The JVM provides abstraction against the operating system on which the application server is deployed. This is obviously because the same WebLogic shipment should run equally as well on Linux as on Windows or Solaris—this is the whole point of Java. The price of the convenience of write once / run anywhere is thus paid for by the JVM abstraction layer.

Under the JVM is an operating system that the JVM must know how to interact with. This requires multiple JVM back-ends for multiple operating systems. For example, on *NIX-style operating systems, pages in memory are allocated differently than on Microsoft Windows, with different system calls (mmap versus VirtualAlloc). The thread API typically also differs between operating systems (POSIX threads versus Windows threads). Thus, the JVM needs OS-specific modules in order to facilitate the execution of the same Java application on different operating systems. Consequently, the operating system itself forms another abstraction layer under the virtual machine.

So, what is the role of a general purpose operating system? The OS abstracts the hardware, making it easier to interact with it programmatically. We can hardly expect a C++ application developer to implement his own synchronization for a particular chipset using atomic assembly instructions or to write his own thread representation. Instead, the OS provides library calls for these kinds of tasks. Thus, the OS forms a second level of abstraction under the JVM.

And finally, in a virtualized world, the hypervisor—while making it possible to run multiple sandboxed operating systems on the same machine—forms a third abstraction layer before we get to the actual hardware.

All these abstraction layers need to communicate with each other. There is overhead here, especially as talking to a lower layer usually requires some kind of privileged action that takes time, destroys caches, and preempts other tasks.

However, if the sole responsibility of the virtualized operating system is to run the JVM, whose sole responsibility in turn is to run the Java application server, don't the various levels of abstraction seem unnecessary and quite wasteful? Why would we need a full-fledged OS such as Microsoft Windows in the middle of our stack, when all we do is run a Java program? The Java program, assuming that it is 100 percent pure Java, doesn't know anything about Microsoft Windows and doesn't use any OS-specific mechanisms. If the Java program is an application server with no GUI, do we even need the functionality to display graphics on screen? If all users and access controls necessary to interact with the system are handled by a model inside the application server, do we even need an OS?

We can make the observation that a JVM is not so far removed from an OS as one might think. It implements JDK library calls to support threads and synchronization. It handles memory management and so on. Without stretching the metaphor too tightly, a JVM is just like a special-purpose virtual operating system.

Maybe a direct-to-hypervisor JVM isn't such a bad idea?

Introducing JRockit Virtual Edition

The case can be made that if there was a way to reap the benefits of virtualized Java without the overhead, much would be gained. If the layers between Java and hardware are kept small enough, there is not just performance to be had, but also the added benefit of simplicity and security. The solution proposed by the JRockit architects is the product JRockit Virtual Edition, or JRockit VE for short.

Note

As a proof of concept back in 2005, we wrote a linker that told us what symbols a JVM deprived of its operating system was missing. The discovery that the list was really quite short was the start of the JRockit VE project.

JRockit VE consists of the JRockit JRE, a collection of pure Java services (for example an SSH daemon), and finally a thin OS-like layer that runs on top of the hypervisor. This layer provides all of the very limited amount of OS functionality that a JVM needs. It is known as the JRockit VE kernel.

JRockit VE is currently available only on x86 platforms.

Note

The commercial versions of the JRockit VE virtualization framework currently only ship with support for running on top of the Oracle VM native hypervisor (and consequently on top of Xen). JRockit VE may, however, also support other hypervisors in the future.

It has always been our design philosophy, as it should be in a virtualization stack, that the target platform for the JRockit VE kernel is hardware and not a hypervisor. The JRockit VE kernel with a small built-in E1000 network driver can boot from a USB stick and run Java applications on any x86 machine out of the box (It is doubtful, however, why this demo, except for the fact that it is really cool, would illustrate any benefits of JRockit VE in cloud computing, but we'll get to that).

JRockit VE also comes with a tool for creating and manipulating Java applications that are to run in a virtualized environment, the Image Tool. When a Java application is virtualized and packaged for use with JRockit VE, it is referred to as a virtual machine image.

Introducing JRockit Virtual Edition

The previous figure illustrates the stack, as it looks for a Java application deployed on JRockit VE. Services like SSH run in Java land, along with the Java application. The JRockit JVM sits on top of the JRockit VE kernel layer that provides all OS functionality needed by the JVM.

Let us now look closely at the JRockit VE kernel to understand both why implementing it is a much smaller undertaking than writing a complete OS, and what functionality we need to make available to the layers above.

The JRockit VE kernel

JRockit Virtual Edition removes the need for an OS under the JVM and makes it possible to run Java directly on top of a hypervisor. Currently, an unmodified Linux version of the JRockit JVM can run directly on top of the JRockit VE kernel. This is, however, expected to change for future releases and the JRockit VE kernel is expected to turn into its own JVM platform, requiring a special version of the JVM. This is to further decrease the number of abstraction layers in the stack and to provide additional simplicity of implementation. The only reason that the JRockit VE kernel currently emulates a Linux API upwards has been the lack of development time to create an additional platform for the JRockit JVM.

Note

The fact that the JRockit JVM currently is a Linux distribution does not impact performance negatively or constrain it to Java-on-Linux levels. The JRockit VE kernel can do plenty with the OS layer to provide a much more ideal execution environment for the Linux JVM. With a specialized JVM, performance will improve even further.

The JRockit VE kernel is conceptually very much like an OS, but far from the real deal. It contains its own thread implementation, scheduler, support for file systems, memory allocation mechanisms, and so on, but is vastly less complex than an operating system.

For one thing, the JRockit VE kernel can run only one process—the JRockit JVM. Also, as a JVM is an inherently secure sandboxed execution environment, we do not need to worry about malicious Java code causing, for example, deliberate buffer overruns. Bytecode verification and all other security aspects of validating executing Java code is handled for us by the JVM already.

An important constraint here is that JRockit VE needs to disallow the execution of arbitrary native code, as there is no way to determine what it does. This is both a functionality and a security concern. Native code can contain operating system calls that only work on a standard operating system and it may also perform any, potentially insecure, task. Disallowing native code, however, tends to be a small price to pay in a modern Java-based server environment. Therefore, JNI is not supported on JRockit VE.

Another example of the limited functionality is the lack of advanced paging mechanisms that would be present in any general purpose OS. The JRockit VE kernel runs just one process and needs just one virtual address space.

The following figure illustrates the various modules in the JRockit VE kernel. They include, among other things, file system implementations, device driver stubs that communicate with the hypervisor, block cache mechanisms, a self-contained network stack, simple memory management systems, and a thread scheduler.

The JRockit VE kernel

The JRockit VE kernel, in its exposed APIs is very *NIX-like. As stated, a distribution of JRockit for Linux can run unmodified on top of the JRockit VE kernel, but this only means that the very limited amount of Linux APIs that JRockit needs have been implemented in the kernel, not that the kernel is Linux-compatible in any way. Typically, the APIs available to the JVM look like POSIX system calls, but have less generic functionality. Given that future JRockit versions become JRockit VE aware, we could avoid most kludges caused by pretending to be Linux. One example of this would be not having to emulate parts of /proc file system in the kernel, as this is the way JRockit on Linux collects information on memory layout. We would also like to remove some OS calls, such as mmap, that look like POSIX calls in JRockit VE, but are not. The standard POSIX version of mmap is very complex, but in JRockit VE only the specific use cases that JRockit for Linux needs have to be implemented. Porting JRockit to an explicit JRockit VE platform would not be too complex an undertaking as all operating system calls in the JVM already exist in a well-defined platform abstraction layer.

In conclusion, it is important not to be taken aback by thinking about the concept of the JRockit VE kernel as a small lightweight OS. It is much less than that and large parts of the complexities required for an operating system are not needed in our kernel. The need to implement and maintain a set of device drivers, in operating systems such as Linux, which is a much larger task than maintaining the actual kernel code, is made unnecessary as JRockit VE requires a hypervisor to run on. The hypervisor will take care of device drivers where necessary and abstract physical hardware for us. The complete JRockit VE kernel module is only around 130,000 lines of C code, large parts making up the network stack.

The virtual machine image concept and management frameworks

The "virtual cloud" is a hot buzzword right now. It is a fairly simple concept to understand—a vast blob of Internet-connected computing resources that can be harnessed without the need to care about individual configurations and individual machines.

A Java application installed on a physical machine is also a well-known concept.

Most cloud solutions today use some kind of management framework that handles application deployments in the cloud, removing the need for individual machines through abstraction, which makes plenty of sense—"the cloud is the computer". Typically, management frameworks are used to deploy entire self-contained guest operating systems, for example virtual Linux distributions, in a server cloud.

Note

A concrete example of a management framework in cloud computing is the Oracle VM Manager software that is part of the Oracle VM native hypervisor. Oracle VM Manager allows the administrator to configure and group clusters of servers in the cloud and deploy virtual machine images on them.

JRockit Virtual Edition originally started out with an ambition to look like "local Java". This meant starting the virtual application and deploying it in the cloud with command line on a local machine. On the local machine, it would look like the virtual application was executing locally, instead of remotely. This was accomplished by, among other things, feeding back JVM console output to the local console. It turned out that this was a very complicated concept to understand and it also led to some degree of confusion: where is an application actually running?

After alpha releases, and user testing, the JRockit VE team decided to go the other way instead—local Java applications should be turned into virtual machine images. These are binary blobs ready for cloud deployment through existing management frameworks like Oracle VM Manager. Controlling the virtual machine image, such as changing its virtual hardware layout and migrating it across server pools, are examples of functionality provided already by the management framework.

Virtual machine images, in the general case, can contain any machine configuration with any operating system. A JRockit VE virtual machine image consists of a complete virtual machine specification and setup for a Java application along with a file system containing said Java application.

We can think of distributing a virtual machine image containing, for example, WebLogic Server to a customer, as shipping the customer a physical machine. On its hard disk is a preinstalled version of WebLogic Server good to go, and all the user needs to do is plug the machine into a power outlet, attach a network cable, and start it up. The main difference in the case of the virtual machine image is that we don't ship the physical machine along with the installed software. We only ship the specification of the machine—how much memory does it have, how many CPUs—and a cloned image of its hard disk. The cloud will provide the resources necessary for emulating the machine in order to run the application. This is what virtualization is all about.

Thus, virtual machine images also remove the need for installing software. Preinstalled software in virtual machines can be deployed directly. This is one of the reasons that virtualization can help reduce IT costs in an organization.

Note

A virtual machine image can be generated from scratch, or assembled, by applying the Image Tool that ships with JRockit VE to a locally installed application. Instances of this image can then be deployed directly into your server cloud. We call this the "physical to virtual" use case. Another use case, however, is for the customer to run software that is shipped in the form of an already assembled virtual machine image (for example WLS on JRockit VE), available from an OEM or software vendor, and not create images of his own.

Many aspects of the machine specification for an existing virtual machine image, for example the amount of memory available to the virtual machine, can be manipulated offline with the JRockit VE Image Tool as well as from the management framework. The virtual machine environment for the virtualized application can vary from being very simple to very complex.

A JRockit VE virtual machine image with a minimum configuration can simply be auto-generated. Typically, the Image Tool only needs to know things like disk size, number of CPUs, and amount of memory in the virtual machine. The JRockit VE kernel requires at least one network interface to work. When booting, the kernel will try to use the DHCP protocol, if available, to configure networking. This makes setup very simple and portable. If DHCP is unavailable on your network, explicit configuration of the virtual network cards needs to be done.

The local file system in the virtual machine image is part of the generated disk image and available to the virtualized Java application once it runs.

The following example shows a very simple, but fully sufficient, configuration file for a JRockit VE virtual machine specification. It describes a virtual machine image that executes a HelloWorld Java program. The virtual machine image can be created using the Image Tool. Similar configuration files can be obtained by querying an existing virtual machine image for its specification.

The JRockit VE config file format is totally hypervisor agnostic.

<?xml version="1.0" encoding="UTF-8"?>
<!-- helloworld.xml -->
<jrockitve-imagetool-config xmlns:xsi="http:// www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation=
"jrockitve-imagetool-config.xsd" version="5.1">
<jrockitve-config memory="512 MB" cpus="1">
<storage>
<disks>
<disk id="root" size="256 MB"/>
</disks>
<mounts>
<mount>
<mount-point>/</mount-point>
<disk>root</disk>
</mount>
</mounts>
</storage>
<vm-name>helloworld-vm</vm-name>
<java-arguments>-Xmx256M HelloWorld</java-arguments>
<network>
<nics>
<nic/>
</nics>
</network>
</jrockitve-config>
<jrockitve-filesystem-imports>
<copy from="~/myLocalApp/HelloWorld/*" to="/"/>
</jrockitve-filesystem-imports>
</jrockitve-imagetool-config>

The configuration describes a machine with 512 MB of RAM and one CPU. The machine contains one hard drive that is 256 MB in size. The virtual machine, once the image is deployed, will show up as helloworld-vm in various management frameworks. At boot time, the JRockit VE kernel will invoke JRockit. JRockit then executes the HelloWorld program, whose .class file (and possibly other resources) are placed in the root directory of the hard drive in the virtual machine. The virtual machine contains one network card (NIC). As no explicit configuration other than that which exists is given, the JRockit VE kernel will use DHCP to establish things like the IP address for the virtual machine when it boots.

Following are a few command-line examples, illustrating using the Image Tool to assemble a virtual machine image and to modify it before deployment. The default behavior is to create a standard Xen or Oracle VM configuration, consisting of a hypervisor-specific vm.cfg file and a system image, system.img, with the virtual hard drive containing the Java application, the JRockit JRE, and the JRockit VE kernel. The following example creates a virtual machine image from the previous specification:

hastur:marcus$ java -jar jrockitve-imagetool.jar
Usage: java -jar jrockitve-imagetool.jar [options]
-h, --help [<option_name>]
-c, --create-config [<config_file.xml>] [<vm_name>]
--create-full-config [<config_file.xml>] [<vm_name>]
-r, --reconfigure <vm_cfg> <op> <field> [<parameter>]*
--reconfigure-service <vm_cfg> <service-name> <op> <field> [<parameter>]*
-f, --file <vm_cfg> <operation> [<parameter>]*
--get-log <vm_cfg> [<output file>]
--repair <vm_cfg> [<auto|prompt|check>]
-p, --patch <vm_cfg> <patch_file>
-a, --assemble <config.xml> <output_dir> [<hypervisor>]
-d, --disassemble <vm_cfg> <output_dir>
-v, --version [<vm_cfg>|<jrockitve_image>]
-l, --log (#) <quiet|brief|verbose|debug>
--force (#)
Options marked "#" are not standalone. They must be used together with other options
hastur:marcus$ java -jar jrockitve-imagetool.jar --assemble helloworld.xml /tmp/outputdir
Assembling the image...
| |
.............................
Wrote 127 MB
Done
hastur:marcus$ ls -lart /tmp/outputdir/
total 327688
drwxrwxrwt 18 root 612 Aug 29 11:09
-rw-r--r-- 1 marcus 270 Aug 29 11:10 vm.cfg
-rw-r--r-- 1 marcus 268435456 Aug 29 11:10 system.img
drwxr-xr-x 4 marcus 136 Aug 29 11:10
hastur:marcus$ java -jar jrockitve-imagetool.jar --reconfigure /tmp/outputdir/vm.cfg get java-arguments
-Xmx256M HelloWorld
hastur:marcus$ cat /tmp/outputdir/vm.cfg
# OracleVM config file for 'helloworld-vm'.
# Can be used with 'xm <start|create> [-c] vm.cfg'
#
# note that Xen requires an absolute path to the image!
name="helloworld-vm"
bootloader="/usr/bin/pygrub"
memory=512
disk=['tap:aio:/OVS/seed_pool/helloworld-vm/system.img,sda1,w']
vif=['']
on_crash="coredump-destroy"

Given an assembled virtual machine image, we can use the JRockit VE Image Tool to query and reconfigure its virtual machine specification. In the following example, we retrieve and change the number of virtual CPUs that should be available in the virtual machine. This will cause changes to the underlying hypervisor specific config file and possibly to the contents of the image (in our example system.img). An assembled image is always uniquely identified by its hypervisor specific config file (in our case vm.cfg for Oracle VM or Xen).

hastur:marcus$ java -jar jrockitve-imagetool.jar --reconfigure /tmp/outputdir/vm.cfg get cpus
1
hastur:marcus$ java -jar jrockitve-imagetool.jar --reconfigure /tmp/outputdir/vm.cfg set cpus 4
Done
hastur:marcus$ cat /tmp/outputdir/vm.cfg
# OracleVM config file for 'helloworld-vm'.
# Can be used with 'xm <start|create> [-c] vm.cfg'
#
# note that Xen requires an absolute path to the image!
name="helloworld-vm"
bootloader="/usr/bin/pygrub"
memory=512
disk=['tap:aio:/OVS/seed_pool/helloworld-vm/system.img,sda1,w']
vif=['']
vcpus=4 #<--- we now have 4 virtual CPUs
on_crash="coredump-destroy"

Note

An assembled virtual machine image can also be reduced to its component parts and disassembled by the Image Tool, but this use case (virtual to physical), exactly like the assembly use case (physical to virtual), is not the only one available to end customers. We also assume that end customers, to some extent, will work with prepackaged virtual machine images that can be reconfigured and manipulated with the Image Tool.

Aside from manipulating a virtual machine image, the Image Tool can also be used to patch an image, with bugfixes or upgrades to the software within, such as the JRockit VE kernel or WebLogic Server. Thus, a pre-packaged virtual machine image can be upgraded by vendor fixes without the need for taking it apart.

The Image Tool can also be used for a number of other common offline manipulation tasks such as extracting log file information from the virtual application or enabling services such as SSH that come pre-installed in every JRockit VE image. Even though the patch framework fully supports patch version control and rollbacks, an implicit safety mechanism in patching machine images is apparent given that an image is just a couple of files on disk: backing up the image is just a matter of copying the files somewhere. Should anything go wrong, they can be easily restored.

Following is another example of querying a JRockit VE virtual machine image for its installed services and enabling one of them—the previously mentioned SSH daemon:

hastur:marcus$ java -jar jrockitve-imagetool.jar -r /tmp/outputdir/vm.cfg get installed-services
sshd (An SSH2 implementation with SCP and SFTP support)
jmxstat (JRockitVE kernel statistics MBean)
sysstat (JRockitVE kernel sysstat statistics)
hastur:marcus$ java -jar jrockitve-imagetool.jar -r /tmp/outputdir/vm.cfg get enabled-services
None
hastur:marcus$ java -jar jrockitve-imagetool.jar -r /tmp/outputdir/vm.cfg enable service sshd
Done
hastur:marcus$ java -jar jrockitve-imagetool.jar -r /tmp/outputdir/vm.cfg get enabled-services
sshd (An SSH2 implementation with SCP and SFTP support)

When the SSH service is enabled in a running virtual machine image, the virtual machine will answer SCP and SFTP requests, given some preconfigured authentication policy.

Finally, the Image Tool can be used to manipulate the file system of a virtual machine image, for example by allowing creation and removal of files and directories. The Image Tool also supports that files from a local file system can be placed in the image and conversely, that files from the image can be copied to a local file system.

hastur:marcus$ java -jar jrockitve-imagetool.jar --file /tmp/outputdir/vm.cfg ls /
[Feb 04 2010] boot/
[Feb 04 2010] jrockitve/
[Feb 04 2010] lost+found/
[Feb 04 16:00 498 bytes] HelloWorld.class
[Feb 04 16:00 358 bytes] VERSION
Done
hastur:marcus$ java -jar jrockitve-imagetool.jar --file /tmp/outputdir/vm.cfg get HelloWorld.* /tmp
Done
hastur:marcus$ ls l /tmp/HelloWorld*
-rw-r--r-- marcus wheel 489 Feb 14 15:36 /tmp/HelloWorld.class

Benefits of JRockit VE

There are several advantages to using JRockit VE as a specialized virtualization solution for Java. The main ones are:

  • Performance and better resource utilization
  • Simplicity
  • Manageability
  • Security

We will discuss them in order.

Performance and better resource utilization

Increased performance in JRockit VE stems from two general areas, the first one being (as we have already mentioned), the removal of unnecessary abstraction layers. With a specialized Java environment for virtualization, some of the "triple virtualization" caused by a combination of JVM, OS, and hypervisor is removed.

The other side to virtual Java performance with JRockit VE is even more interesting—there are several areas where being the link between the hypervisor and the JVM can provide us with information that, if correctly used, may outperform standard virtualized operating systems or even in the right environment (although it might sound too good to be true), physical hardware. We will address these intriguing issues in the section A look ahead—can virtual be faster than real at the end of this chapter.

Getting rid of "Triple virtualization"

In a normal operating system, certain operations, such as system calls, need to run in more privileged modes on the hardware. Modern hardware typically has some kind of hierarchical protection domains. All code executes in one of these domains. They go from least privileged access (userland) to most privileged (kernel). On x86 hardware, these protection domains are referred to as rings, and a more privileged operation is said to be running in a ring with lower ring number. Ring 0 is the most privileged level and corresponds to kernel access. Non-trusted user code, on the other hand, must run in a less privileged ring. As soon as the user code needs to execute a privileged operation, such as a system call, the CPU needs to change rings, which is a very expensive operation, requiring synchronization and potentially destroying all caches.

As the JRockit VE kernel contains OS-like subsystems of its own and because it relies on the hypervisor for hardware interaction, there is nothing stopping it from executing mostly in Ring 3, userland on x86, reducing (but not altogether removing) the need for ring transitions.

Note

Here is a hypervisor implementation detail, that may provide further insight into how protection domains work—a virtualized guest operating system on x86 typically runs its kernel operations in Ring 1, leaving the more privileged Ring 0 to the hypervisor. This doesn't matter to the guest.

The following figure illustrates the execution path of a network system call in a JVM running on a normal Linux operating system compared to doing the same in the JRockit VE kernel. The dashed vertical lines are the time axes.

Getting rid of "Triple virtualization"

The system call starts with Java code calling a function in the java.net package. Control is then transferred gradually through the layers, down to the actual hardware, where the network driver executes assembly instructions. The dashed lines correspond to expensive privileged operations, such as ring changes, needing to take place. The overhead for doing the same thing in JRockit VE is vastly smaller.

Hopefully, this makes a case that virtualization overhead can be aggressively reduced if the OS is replaced with a more specialized layer. This is what gives JRockit VE a unique and attractive selling point. One of the biggest problems with implementing cloud computing, as discussed early in this chapter, is the performance loss incurred from going virtual. By replacing the operating system layer, JRockit VE can significantly reduce that overhead, when compared to traditional virtualization solutions.

Memory footprint

The JRockit VE kernel is a self-contained boot image that is just a few megabytes in size. This small amount of storage, except for a few configuration files and the JRE, is all the space in a JRockit VE-based virtual machine image not taken up by user code. A modern operating system, even a JeOS (Just enough OS) implementation, is on the order of several hundred megabytes in its simplest install.

The small size of a JRockit VE system and its kernel ensures that the amount of system memory in the virtual machine that can be used for running the actual Java application (i.e. resources available to the JVM) is maximized. This is most important on 32-bit setups, which still is a fairly common virtual machine representation in a cloud configuration.

Manageability

Manageability comes in two flavors—offline manageability, on the virtual machine image level, and online manageability, the ability to deploy and control a running virtual machine image in a cloud computing environment.

For an undeployed JRockit VE virtual machine image, all interaction with its "outside world" is handled by the Image Tool that is shipped with the JRockit VE product and its derived products, such as WLS on JRockit VE. Any aspect of a JRockit VE virtual machine image, file system, virtual machine configuration, enabled services, and so on, can be manipulated offline with the Image Tool in a hypervisor agnostic way.

The other very visible aspect of manageability is the virtual machine image concept. Given that a JRockit VE virtual machine image conforms to a known hypervisor format, it may be introduced into another resource management system, such as Oracle VM Manager.

Oracle VM Manager already exists as a product today. The typical use case is that it enables the administrator to work with several virtualized versions of Oracle Enterprise Linux. It requires little or no modification to work with other kinds of virtual appliances in virtual machine images—for example instances of WLS on JRockit VE, that are packaged on top of JRockit VE. To the management framework, one of these "WebLogic blobs" will look the same as any other virtualized guest. The ability to fit into existing virtualization management frameworks makes adoption problems for JRockit VE a non-issue. We have seamlessly removed the standard operating system layer from the virtual machine image.

Simplicity and security

It may not be a universal truth that security follows simplicity, but with JRockit VE we shall see that this is the case.

A full-fledged operating system is a complex beast. It needs to be, as it contains a jungle of system daemons and user applications such as web browsers and e-mail programs. It also has to provide a generic multi-tasking environment and enable multiple processes to co-exist. There are usually several entry points to a remote workstation running a standard OS, such as open ports for network services, login protocols, and so on.

As the kernel layer in JRockit VE provides only the bare necessities required to run a JVM, the inherent complexity of the system is orders of magnitude smaller. As mentioned, there is only one preinstalled service, sitting on top of the kernel, allowing remote access—a 100 percent pure Java SSH daemon. This service is also disabled by default. It needs to be explicitly enabled by the creator of a JRockit VE virtual machine image in order to work. With the low number of entry points from the outside world, no native code allowed, and the JVM handling verification of all potentially malicious Java code, security is by design much better than that which can be provided in a more complex environment.

Also, as previously mentioned, the "OS" itself, the JRockit VE kernel, can only run one process—the JVM. So, we have no process and resource separation problems that can make JRockit VE more insecure.

The JVM maintains the security of an executing Java application according to the Java Virtual Machine specification. Given that native code is banned, the sandboxed JVM model can fully protect us against buffer overruns and malicious code. No other memory protection is needed for the running Java program than the intrinsic one provided by the JVM. So, by excluding native code from our execution model, we get both simplicity and security at the same time.

A generic operating system also normally allows several users with different access control levels. This has to be supported down to the process and file system levels. The JRockit VE "OS" allows zero users. The only user is the implicit process owner of the JVM. Managing users is left to the Java application. The typical use case, running an application server, is ideal, as it usually contains an intrinsic implementation for user accounts and access rights. Outsourcing user access controls to the Java application server neither causes a restriction for our common use cases nor a security problem.

Configuring a generic operating system requires several utilities or configuration files. Configuring JRockit VE virtual machine images requires modifying and applying changes from just one configuration file that works auto-generated out of the box, or using an existing management framework.

Approximate number of

JRockit VE

JeOS

Linux

Config Files

1

100

1,000

Commands

10

500

3,000

Command/Kernel Params

100

10,000

50,000

Admin tools

1

200

500

Size (MB)

3(*)

200

1,000

Average ratio to JRockit VE

1

50

500

Consider the previous table that presents a very rough comparison of the complexity between a full-fledged OS (a server Linux distribution), a stripped down "Just Enough OS" Linux distribution (or JeOS), and an application running on JRockit VE. Keeping a small system secure is feasible, but it gets exponentially more difficult when size and complexity grows.

*We need to ship the JRE as well, but let us for the sake of argument consider it a userland application on the same level as the Java application. This is technically true.

Constraints and limitations of JRockit VE

The two major limitations of JRockit VE are lack of JNI support and lack of GUI.

As has been mentioned, the JRockit VE kernel supports only pure Java. This is because allowing arbitrary native code would obviously require massive security efforts and a more "complete" operating system. This is not too much of a problem, as these days most well-written Java applications for the server side are 100 percent pure Java and perform well on modern JVMs to boot. The lack of JNI support turns out to be a non-issue. While we still execute native code in the form of libraries that the JVM may need, this is native code known not to perform any dangerous or unimplemented operations.

JRockit VE can currently only export information through its console, not through a GUI. The console is limited to text output only, i.e. writes to System.out and System.err. Console output can also be redirected to log files in the local file systems or to NFS shares on the network. Applications with graphical user interfaces are consequently not supported. Again, for the server side this turns out not to be much of a problem.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset