The class file verifier supported by Java 2 Standard Edition (J2SE) is not suitable for small, resource-constrained devices. The J2SE verifier requires a minimum of 50 kB binary code space, and at least 30-100 kB of dynamic RAM at run time. In addition, the CPU power needed to perform the iterative dataflow algorithm in the standard JDK verifier can be substantial.
We have designed and implemented a new, two-phase class file verifier that is significantly smaller than the existing J2SE verifier. The runtime part of the new verifier requires about 15 kB of Intel x86 binary code and only a few hundred bytes of dynamic RAM at run time for typical class files. The runtime verifier performs a linear scan of the byte code, without the need of a costly iterative dataflow algorithm. The new verifier is especially suitable for KVM, a small-footprint Java virtual machine for resource-constrained devices.
The new class file verifier operates in two phases, as illustrated in Figure 1:
The runtime class file verifier requires all the subroutines to be inlined, so that class files contain no jsr
, jsr
_w, ret, or wide
ret
instructions. Additionally, the runtime verifier requires the methods in class files to contain special StackMap
attributes. The preverifier tool performs these modifications to normal class files generated by a Java compiler such as javac. A transformed class file is still a valid J2SE class file, but with additional attributes that allow verification to be carried out efficiently at run time.
javac
(the Java compiler) may be modified to perform these changes automatically. In that case, the preverifier tool will no longer be necessary.
The preverifier tool shipped with the KVM release is a C program that contains code extracted from the JDK 1.1.8 virtual machine implementation as well as code specifically written for inlining subroutines and inserting the StackMap
attributes. The program compiles and runs on Windows and Solaris, and can be ported to other development platforms relatively easily.
The preverification phase is usually performed at application development time on a development workstation. For example, if you weren’t using a preverifier, you would typically compile Foo.java
using javac
like this:
However, when using the preverifier, you would place the output of javac
in a separate directory and then transform the resulting class files using the preverifier. For example:
The above preverifier command transforms all class files under mydir/
and places the transformed class files in the current directory (as specified by the -d
option).
Makefiles in the KVM distribution invoke the preverifier automatically.
More generally, the preverifier is invoked as follows:
Preverifier options and accepted input file formats are explained in more detail below.
The preverifier accepts a number of arguments and options.
.jar
, .JAR
, .zip
or .ZIP
suffix../output
.-classpath
and -d
options must be enclosed within double quotes. When the corresponding options are used from the command line, quotes are not required (unless the directory/file name parameter contains spaces.)
For example, the contents of <filename>
under Win32 may appear as follows:
-classpath “api/classes; aaa bbb ccc/samples/classes” -d “output” -verbose HelloWorld1 HelloWorld2 HelloWorld3
The preverifier can accept input files in three different formats:
To preverify a single class file or a number of class files, simply include the class file(s) after the command line options:
To preverify all the Java class files contained in a directory or set of directories, invoke the preverifier tool as follows:
To preverify all the Java class files contained in one or more JAR files, invoke the preverifier tool as follows:
Any combination of individual class files, directories or JAR files should be possible.
Obviously, the library classes can also be contained in a JAR/ZIP file, as illustrated by the line below:
Output is generated differently depending on input parameters. If individual files are specified, the preverifier tool performs preverification separately for each input file. For each directory name, the preverifier recursively transforms every class file under that directory. The JAR file handling is discussed in the next section.
Since KVM 1.0.2, the preverifier tool provided with the KVM allows input files to be provided as a JAR file. Given a JAR file that contains un-preverified Java class files, the preverifier tool will automatically generate an identical JAR file containing preverified class files.
This is performed as follows: First, the preverifier will check the file extension (.jar
, .JAR
, .zip
or .ZIP
file suffixes are acceptable) and validate that the file is in valid Java Archive format. Then, the class files will be extracted from the JAR file. For each class name extracted from the JAR file, the preverifier tool will perform the necessary transformations, and will then store the output file into a temporary directory tmpdir
. After all the class files have been transformed successfully, a new JAR file with the same name will be created under <output>
directory containing all the verified classes previously stored in tmpdir
.
If the preverifier is run in non-verbose mode, any errors that may have occurred during the JAR creation will be logged in the <output>/jarlog.txt
file, where <output>
refers to the directory in which output classes will be written. If no errors occur during JAR creation, the <output>/jarlog.txt
file will be removed. Directory tmpdir
is also removed after the JAR file creation.
Runtime part. The runtime part of the verifier does not generally require any porting efforts, as it is closely integrated with the rest of the KVM, and is implemented in portable C code.
The process of porting the runtime verifier from KVM to another virtual machine is beyond the scope of this document.
Preverifier part. The preverifier is also written in C. By default, the preverifier is available for Windows and Solaris, but it should be relatively easy to compile it to run on other operating systems as well. Note that the preverifier codebase is derived from the “Classic” Java virtual machine, so the preverifier implementation looks quite different from the rest of the KVM codebase.
The sources for the preverifier are in the directory tools/preverifier/src
.
On Solaris, you can build the preverifier by typing the “gnumake” command in the tools/preverifier/build/solaris
directory. This compiles and links all .c
files in the tools/preverifier/src
directory, and places the resulting executable file in the tools/preverifier/build/solaris
directory.
On Win32, you can build the preverifier by typing the “gnumake” command in the the tools/preverifier/build/win32
directory. This compiles and links all .c
files in the tools/preverifier/src
subdirectory, and places the resulting executable file in the tools/preverifier/build/win32
directory.
KVM Porting Guide , CLDC 1.1 |
Copyright © 2003 Sun Microsystems, Inc. All rights reserved.