Contents Previous Next

Chapter   13

Class File Verification


13.1 Overview

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:

[D]

FIGURE 1  –  Two-phase verification

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.


Note – In the future, 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.

13.2 Using the preverifier

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:

        javac -classpath kvm/classes Foo.java 

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:

        javac -classpath kvm/classes -d mydir Foo.java 
        preverify -classpath kvm/classes -d . mydir 

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.

13.2.1 General form

More generally, the preverifier is invoked as follows:

        preverify <options> <input files> 

Preverifier options and accepted input file formats are explained in more detail below.

13.2.2 Preverifier options

The preverifier accepts a number of arguments and options.

-classpath <directories> | <JAR files> 

Note – When the command line arguments are read from a file, parameters must all be specified on a single line and the parameters to the -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 

13.2.3 Supported input file formats

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:

        preverify -classpath kvm/classes File1 File2 ... 

To preverify all the Java class files contained in a directory or set of directories, invoke the preverifier tool as follows:

        preverify -classpath kvm/classes dir1 dir2 ... 

To preverify all the Java class files contained in one or more JAR files, invoke the preverifier tool as follows:

        preverify -classpath kvm/classes Jar1.jar Jar2.jar ... 

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:

        preverify -classpath classes.zip File1 File2 ... 

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.


Note – A non-zero error status is returned if preverification fails for any reason.

13.2.4 JAR support in preverifier (since KVM 1.0.2)

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.


Note – When preverifying class files contained in JAR files, the preverifier tool will internally call the standard JAR tool to repackage the output files into a new JAR file. To accomplish this, the standard JAR tool must be accessible on your file path.

13.3 Porting the verifier

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.

13.3.1 Compiling the preverifier

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.

 


Contents Previous Next KVM Porting Guide
, CLDC 1.1