Back to Project Pages Home
JAPT (Java optimizer)
Japt is a tool for optimizing java programs. Japt makes use of the JikesBT java class manipulation library and its own proprietary class manipulation functionality to optimize java class files. This lists some of the basic features of Japt. Advanced extensions (inlining, reduction, obfuscation, escape analysis, remapping, assembler/disassembler, instrumentation, etc) are not covered in this document. This document covers the basic concepts of Japt from a user’s perspective.
2.1 Command Line
2.2 Extensions
2.3 Internal and External Classes
3 Loading Classes and Resources with the Load Extension
3.1 Loading
3.2 Wildcards
4.1 The Jar Generation Extension
4.8 The Class File Generation Extension
Not all options are listed here, the more obscure options are omitted here for the purpose of clarity.
usage: japt [options...]
japt optimizes java classes
basic options:
-help print out this message
-version print out program version
-sysProps print out the system properties
-log xxx write to the named log file
-quiet quiet mode
-macro xxx xxx define a macro with the given name and value
-noResolveRuntimeRefs leave method/field references unresolved
-incrementalLoad turn off auto load
@xxx read named file for additional options
load options:
-icp xxx append named jar/dir to internal cls srch path
-cp xxx append named jar/dir to class search path
-loadFile xxx load named file as internal classes/resources
-loadClass xxx load named class(es) (from class path)
-loadResource xxx load named resource(s) (from class path)
-includeClass xxx include named class(es)
-includeWholeClass xxx include all members with the named class(es)
-includeLibraryClass xxx include non-prvt members with named class(es)
-includeAccessibleClass xxx include pub/prot members with named class(es)
-includeField xxx include named field(s)
-includeMethod xxx include named method(s)
-includeMainMethod xxx include main method with named class(es)
-includeMethodEx xxx include named method(s) independent of owner
-includeExtLibraryClass xxx include non-private members with named class(es) and known overriding/implementing methods
-includeExtAccClass xxx include public/protected members with named class(es) and known overriding/implementing methods
-startupClass xxx specify named manifest main class
-verify verify internal classes and methods
-optimize perform bytecode optimization
program extensions:
-extension xxx use named program extension
The following built-in extensions are available:
-load
-dirOutput
-jarOutput
Combining "-extension xxx" with "-help" or for example "-inline" with "-help" will print out the available
options for the named extension following this message.
jar generation options:
-output xxx write to named output jar file or directory
-removeAttribute xxx remove the named attribute(s)
-removeStackMaps remove stackmap table attributes from code
-addStackMaps add stackmap table attributes to code
-excludeResource xxx exclude the named resource(s)
-includeZippedResources include resources contained within archives
class generation options:
-dir xxx write to named directory
-removeAttribute xxx remove the named attribute(s)
-removeStackMaps remove stackmap table attributes from code
-addStackMaps add stackmap table attributes to code
-excludeResource xxx exclude the named resource(s)
-includeZippedResources include resources contained within archives
Users of Japt should be familiar with several concepts.
Getting started, the user should be familiar with the notion of extensions and the intricacies of the japt command line.
In order to make modifications and optimizations to classes with Japt, the user should be familiar with the concept of internal versus external classes, as well as the concept of the application (or library) interface.
Japt may read options from the command line or from options files. To read options from a file, use the option “@fileName”. The options contained in the file will be parsed immediately when japt encounters the directive.
Macros can be useful if you are creating many options.
Use:
-macro name value
This will cause any appearance of:
{{name}}
on the command line or in options files to be replaced with:
value
If Japt encounters an option containing the string “{{xxx}}” for which no macro for xxx was defined, Japt will search the System properties for the matching value.
The built-in macros are:
current.file.dir: the directory containing the current options file
current.file: the current options file
current.character.encoding: The string returned by the java code new OutputStreamWriter(System.out).getEncoding()
/: platform independent path separator
For instance,
{{current.file}}
appearing in an options file will be converted to the file name.
All work by Japt is done by extensions. Extensions are executed in the order that they are specified on the command line and in options files. To specify an extension, use “-extension extensionName”. Extensions are described further below.
Japt can create a log file detailing warnings, errors and information produced by Japt and its extensions. To specify a log file, use the option “-log logFileName”.
Japt is built with an extension framework. An extension is an implementation of the interface com.ibm.ive.tools.japt.commandLine.CommandLineExtension. An extension has full access to the JikesBT and Japt public APIs. Japt executes extensions one-by-one, with each extension altering the classes loaded and/or stored by Japt, leaving them in an altered state when the extension has completed execution.
Extensions are specified on the Japt command line, with the option “-extension extensionName”. Certain built-in extensions can be specified by their own unique command line options (for convenience), such as “-jarOutput”.
The extensions are executed in the order that they appear on the command line.
Each extension has its own extension-specific command line options. These options must appear after the extension has been specified on the command line.
The same extension may be executed more than once. In such cases, extension-specific command line options apply only to the last extension as specified on the command line. If an option is applicable to more than one extension, the same rule applies.
Japt defines two types of classes, internal and external. Internal classes are considered internal to the application or library at hand. These classes and resources are considered part of the working set and can be altered by Japt and any extension of Japt. External classes are considered supporting classes and cannot be altered. When writing classes and resources to a jar file or other form of output, only the internal classes and resources will be written.
For example, a typical invocation of Japt might make alterations to the classes of a stand-alone application but not the J2SE classes that the application requires.
Whether a class is an internal class depends upon which class path location it originates from. Each class path location is identified as either internal or external.
When invoking Japt, if the user intends to make modifications to the internal classes and resources, the user must be careful to explicitly indicate the entire interface of the application. The interface consists of all elements of the internal classes and resources that may be accessed from outside the application or library, either from the external classes or from elsewhere.
The identifying characteristics of such elements cannot change, so that the application can be accessed in exactly the same manner regardless of the internal modifications by Japt.
For example,
Japt might change or remove methods and fields in an application library, but
the identifying characteristics of the API cannot change. API methods cannot
be removed, their names cannot change, their arguments cannot change, their
access permission modifiers cannot be made more restrictive, and so on.
For a stand-alone application, the interface often consists of just the main method and its containing class which is invoked by the java virtual machine at startup. For libraries, the interface consists of the complete public API. For integrated apps like servlets, the interface consists of the specially predefined classes in the application that may be instantiated, or the methods in the application that may be invoked from an outside source.
If a class is part of the interface, then this does not necessarily mean that its contents are also part of the interface, and vice-versa.
For instance, an internal class that is subclassed by an external class may be part of the interface (the internal class is accessed externally through the action of inheritance), but if none of the internal class methods or fields are accessed from elsewhere then the contents of that class are not part of the interface.
By the same token, an internal class C that subclasses an external class D might not necessarily be part of the application interface, but if that class C overrides methods in D, then those overriding methods may be part of the application interface, since they can be invoked externally.
The use of the reflection API in java may also create elements of the interface. Any class accessed by the Class.forName construct or the “.class” language construct may become part of the interface, for such classes can then be entered dynamically at run-time by the virtual machine.
Before any class manipulations or optimizations can begin, japt will load the classes and resources as specified, making its own use of the load extension.
When loading, the user must distinguish between the internal and external classes. All internal classes must be loaded. Japt need not load all external classes to function properly, but it is generally beneficial, so it is advisable to load all external classes even though they cannot be changed.
To specify a location on the classpath that will be used to load internal classes, the “-icp” class path option is used. Additionally, internal class path locations are specified with the “-loadFile” option, the difference being that all classes found at that location will be loaded immediately. For external class path locations, the “-cp” class path option is used.
To load classes, the user must generally identify the complete interface and specify the interface using options of the form “-includeXXX”. Any class, method, field or resource that is included is considered part of the interface. This will cause the interface and all supporting classes to be loaded. In general, this is enough to load all required internal and external classes.
Optionally, classes may be loaded using “-loadFile”, however for any manipulations and optimizations it is still necessary that the interface be specified.
The “-loadClass” and “–loadResource” options are also used to specify classes and resources to load, but whether they are identified as internal or external is dependent upon where they are found, as by the options “-icp”, “-cp”, and “-loadFile”.
The “-optimize” option is capable of making optimizations to bytecode, such as removing unreachable code and altering certain bytecode sequences.
The “-verify” will perform some extensive verification on the internal classes. This will not guarantee that verification performed by a java virtual machine will pass, however. But it can help to confirm that the classes are well structured or provide helpful information regarding why the classes are not well-structured.
Any option used to specify a class, field, method or resource will accept wildcards. The available wildcards are:
*: any sequence of characters
^: any sequence of characters that does not include either of the separators ‘/’ or ‘.’
e.g. to include all classes in java.lang and subpackages:
-includeClass java.lang.*
e.g. to include all classes in java.lang:
-includeClass java.lang.^
e.g. to include the methods in java.lang.Object:
-includeMethod java.lang.Object.^
e.g. to include all methods:
-includeMethod *
e.g. to include all methods in the default package:
-includeMethod ^.^
e.g. to include all classes and their public, protected and package methods and fields in java.lang and subpackages:
-includeLibraryClass java.lang.*
Details about the load extension are in section 3. This sections lists some additional extensions.
The jar generation extension is specified by:
–jarOutput
This extension is used to write all internal classes to jar files. The target directory or jar file is specified by:
-output fileName
If a directory is specified, a set of jar files will be created corresponding to the classpath entries the individual classes were obtained from.
There is an option to specify that the jar entries are not to be compressed, “-noCompress”. Any loaded resource can be excluded from the jar files by specifying the option “-excludeResource”, or optionally the user can use the option “-includeZipped” to ensure any resource contained within a jar or zip file on the classpath will be written to the output jar(s).
This extension also contains options that allow the user to remove various items from the written classes. The user may specify any specific attribute to be removed by using the “-removeAttributes” option. The user should consult the java virtual machine specification for a list of specification-defined attributes that may be excluded.
By default, certain groups of attributes are automatically removed (Note: this behavior is expected to change so that removal is no longer the default behavior). There are options to override this behaviour.
To prevent the removal of attributes used by debuggers use “-noStripDebugInfo”. This will prevent the removal of the attributes SourceFile, SourceDebugExtension, LineNumberTable, LocalVariableTable and LocalVariableTypeTable.
To prevent the removal of attributes used to denote information about the original source file, use “-noStripSourceInfo”. This will prevent the removal of the attributes InnerClasses, Synthetic, Deprecated, EnclosingMethod and Signature. These attributes have no influence in runtime behaviour other than influencing information derived from the reflection API.
To prevent the removal of attributes used to store annotation information, use “-noStripAnnotations”. This will prevent the removal of the attributes RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations, RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations and AnnotationDefault. These attributes have no influence in runtime behaviour other than influencing information derived from the reflection API that is annotation related.
There are options to control the removal of the stack map table attributes. The options “-addStackMaps” and “-removeStackMaps” will add and remove these attributes from the class files. The option “-addStackMaps” takes precedence over the options “-removeStackMaps” and “-removeAttributes StackMapTable”.
The class file generation extension, specified by the “–dirOutput” option, is used to write all internal classes to the file system. The target directory or jar file is specified by the “-dir” option.
All other options behave in the exact same way as they do with the jar generation extension.