Super Prev Next

Deprecated features

Features described in this sections are no longer supported and will be removed in the next major release of Excelsior JET.

To quickly check if these features are used in your projects, switch the CHECKDEPRECATED option ON

    +CHECKDEPRECATED

in the project file and try to re-compile it. If usages of any deprecated feature are found, the compiler terminates with the respective error message.


Super Prev Next

Complementary techniques for JIT compilation


Super Prev Next

JIT compiler selection

The JET Runtime comes with two JIT compilers:

optimizing

This JIT compiler is essentially the main static compiler, scaled down and adapted for runtime use.

fast

This compiler implements a few low-cost optimizations, and thus is an order of magnitude faster than the optimizing JIT compiler. The Fast JIT compiler is enabled by default.

Future versions of Excelsior JET will not include the Optimizing JIT compiler. Instead we will make the Fast JIT compiler produce better code

The differences between the two compilers are summarized in the following table:

Characteristic Optimizing JIT Fast JIT
Compilation speed Low (order of magnitude slower than HotSpot) High (comparable to HotSpot)
Code quality High (somewhat below the static compiler) Moderate
Memory requirements High Moderate

Note: If the optimizing JIT compiler fails to compile a method due to lack of memory or inability to restore the method’s structure suitable for optimizations, which may be caused e.g. by obfuscation, it always invokes the fast JIT compiler for such a method.

You select either optimizing or fast JIT compiler on Options page of the JET Control Panel. Another way to force using a particular JIT is setting the system property jet.jit.optimizing or jet.jit.fast, respectively.

If you use the Optimizing JIT compiler, it may run out of memory when compiling very large methods. In such case, you can set the jet.jit.heap.size VM option that defines the maximum amount of memory the JIT compiler is allowed to use. Default value is 128 megabytes.


Super Prev Next

Caching JIT’ed code

Note: information in this section is not applicable to the Standard Edition and 64-bit version of Excelsior JET.

To reduce the overhead of dynamic compilation, the JET Runtime is capable of caching the code produced by the JIT compiler during execution. Once a JIT cache is created, it may be reused by the application on next launches so that JIT compiler will not be invoked for the cached classes. To provide correctness, the JET Runtime performs consistency checks to ensure that the bytecode being loaded has not been changed since the previous run. If the checks fail, JIT cache is (partially) rejected, that is, the outdated code is not used. In place of it, the JIT compiler produces an up-to-date version of the cache.

You enable the caching mechanism for your application on Options page of the JET Control Panel or by setting the system property jet.jit.cache.

Technically, JIT cache is organized as a directory that contains a set of shared libraries with the cached code and a cache descriptor file. The JET Runtime consults the cache descriptor when it performs consistency checks or looks for a piece of the cached code.

By default, the JIT cache directory has the name jittemp and is located in:

For a conventional executable:

the directory which is set current when the executable is launched (if applicable, the Working Directory property of the respective shortcut, otherwise the directory containing the executable file)

For a shared library accessed via the Invocation API:

the current directory of the calling process at the moment of the first call to JNI_CreateJavaVM()

You may assign a different location for the cache directory on Options page of the JET Control Panel or by setting the system property jet.jit.cache.dir, for instance:

    -Djet.jit.cache.dir:/tmp/jitcache

Note: In general, using an absolute pathname for the cache directory is not recommended as it may cause troubles on deployment. If you want to rename the cache directory or change its location on end user systems, specify the jet.jit.cache.dir property when packaging your application for deployment (see Editing Java system properties for details.)


Super Prev Next

JIT cache optimization

Note: information in this section is not applicable to the Standard Edition and 64-bit version of Excelsior JET.

This section describes JIT Cache Optimization, that enables you to use the JET static compiler to optimize applications that rely on custom classloaders.

JIT cache optimization is a three-step process:

  1. Create a JIT cache by running your application in a special mode, when the classes processed by the JIT compiler are flushed to disk.
  2. Run the main JET compiler against the classes collected on Step 1. The result is one fully optimized shared library and the new cache descriptor.
  3. Replace the cache contents with the files created on Step 2.

Alternatively, you may use the xjava launcher to run your entire application through the Caching JIT compiler and then optimize it.

STEP 1.
Create a JIT cache with flushed classes

Suppose you have an application that uses the JET Caching JIT compiler and you set a cache directory, for example, MyTemp:

export JETVMPROP=-Djet.jit.cache -Djet.jit.cache.dir:MyTemp
./MyApp

First, set the jet.jit.save.classes property to flush all dynamically compiled bytecode to disk for subsequent recompilation. Class flushing has a positive side effect: it allows you to pre-compile even those classes which do not exist on your system in the form of class files (e.g. if they are dynamically created at run time).

Note: You may use jet.jit.save.classes on the developer’s machine only and disable it in the compiled application if you find that it may cause security violation. Turn DISABLECLASSSAVING option ON in your project file to prohibit class flushing on end users’ systems.

After that, you run your application using the JET Caching JIT compiler to create a JIT cache. Along with compiled code, the dynamic compiler creates a cache descriptor in your JIT cache directory. Cache descriptor is a plain text files named

    jitJET-version-code J2SE-version-code.cache

(for instance, jit37023.cache).

STEP 2.
Fusing JIT cache

Create a separate project specifying the cache descriptor as a source:

    ------------- fuseCache.prj -------------
    
    -lookup=*.cache=MyTemp
    
    +gendll
    -outputname=fusedCache
    
    !uses path-to-application-project-file
    
    % JETVER/VCODE hold JET/JRE version codes
    
    !module jit$(jetver)$(vcode).cache
    
    -----------------------------------------

and build it as

    jc =p fuseCache.prj

As a result, you will get a new cache descriptor (e.g. jit31523.cache) created in the MyTemp directory and fusedCache.so created in the current directory.

STEP 3.
Using the Newly Fused Cache

At this point, you may remove all files from MyJITTemp except the cache descriptor and copy the newly created fusedCache.so to that directory. Also, remove jet.jit.save.classes property setting.

Now, if you run your executable, it will automatically use the fused cache.


Super Prev Next

Incremental fusion

You may fuse JIT Cache incrementally. For that, follow the steps described in JIT cache optimization, but do not delete flushed classes and leave the jet.jit.save.classes setting intact on Step 3. If your application creates new cache entries that you wish to fuse with the shared library created at previous steps, just perform the procedure again. This saves time of dynamic compilation because the cached code is reused and compilation occurs only for newly loaded classes. To save time of static recompilation of JIT cache, you may specify =s switch to enable the incremental build mode as

    jc =p =s fuseCache.prj

When you decide to stop the process, remove jet.jit.save.classes setting and run your application without flushing classes.


Super Prev Next

JIT cache optimization with xjava

You can optimize JIT cache using the xjava launcher (see xjava launcher) with the following options:

-Xenduser

Do not cache class files.
-Xcachedir:directory

Set the JIT cache directory. The default is the “jittemp” subdirectory of the current directory.
-Xcompile[:launcher-name]

Compile the JIT cache into a single shared library using the main JET compiler and generate a custom launcher launcher-name.

If launcher-name is not specified, the launcher will be named after the main class specified on the xjava command line (or after the jar file if the -jar option is used.)

-Xuseprj:prj-file

Retrieve options for JIT cache compilation from prj-file. This option has no effect if -Xcompile is not specified.

Note: Only the options that affect code generation will be retrieved from prj-file.

-Xgui

This option is ignored on Linux.

The -Xcompile option changes the behavior of xjava completely. Instead of running your application, it does the following:

  1. recompiles the classes cached on previous runs into a single shared library, essentially automating Step 2 of the JIT cache fusion process for you.
  2. creates a custom launcher — a small executable that loads that shared library and runs your application.

Any command-line options other than -Xcompile are hard-wired into the custom launcher, so the correct usage is to add -Xcompile to the options you previously specified:

    xjava -cp MyLib.jar -Dfoo=bar -Xmx256M foo.bar.Main
    xjava -cp MyLib.jar -Dfoo=bar -Xmx256M -Xcompile foo.bar.Main

If you want to change the default settings for JIT cache compilation, use the -Xuseprj:prj-file option, where prj-file is a regular JET project file. xjava ignores prj-file directives that do not affect code generation.


Super Prev Next

Usage example

To begin using the xjava launcher, you normally just need to replace the “java” / “javaw” command with “xjava”. For instance, the following command:

    xjava -cp MyLib.jar foo.bar.MainClass

will run your application with the JIT compiler caching files in the ‘jittemp” subdirectory of the current working directory. Then, you can optimize that cache by adding the -Xcompile option:

    xjava -Xcompile -cp MyLib.jar foo.bar.MainClass

The result will be the custom launcher foo.bar.MainClass, optimized cache shared library, and new cache descriptor. The -cp MyLib.jar option will be hardwired into the launcher. Now you may run the optimized application by typing just

    foo.bar.MainClass

To deploy the optimized application, create a new package in JetPackII and add the launcher executable to it. JetPackII will recognize the launcher and prompt you for adding the optimized cache to the package. See Adding files using filechooser for details.


Super Prev Next

Splash screen control extensions

If startup of your application takes longer than you would like it to do, the thumb rule is to show a splash screen. It definitely relieves the loading process from the end user’s perception, moreover, the splash may contain information about your product and company.

The splash screen functionality appeared in Java API since Java SE 6. For more details, see

http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/splashscreen

Excelsior JET extends that functionality as follows:

All you need to do is to specify the necessary splash settings to the JET Runtime.


Super Prev Next

Displaying a splash

If the splash image has been specified in the manifest of the application’s JAR file, the respective image will be obtained automatically:

Otherwise, you need to assign the application a splash screen image manually:

The supported image formats are PNG, GIF and JPEG, including images with transparency, translucency, and animation.

You may convert images to required format using a third-party image processing tool.

Once assigned, the splash will quickly appear at the very startup of the application (hence the name InstantSplash.)


Super Prev

Suppressing a splash

There are various options to control when the splash screen image shall disappear.

An obvious behavior of the splash screen is to disappear when the main application’s window is opened. However, it is less obvious how to determine what window is the main one (consider an application that opens auxiliary windows such as console, list of warnings, or some dialogs before the main window.) You may choose one of the following "auto-hide" policies:

  1. Hide the splash screen when application opens any window, irrespective of what particular API (JFC/Swing, SWT or something else) is used. This is default.
  2. Hide the splash screen when application opens a particular window, depending on the window title.
  3. Hide the splash screen as the application opens any AWT frame. This policy is not available for Java 5 applications.

Note: By default, the splash screen disappears as the application opens any AWT frame. If you choose the other option, the following limitations apply: translucency in the splash image is not supportted .

If you want to change the default policy, do the following:

Another option that controls the splash screen behavior is a splash delay. You may wish to delay splash disappearance, e.g. to let the user enjoy your artwork. For that, specify the number of seconds you want it to stay on the screen:

Note: The splash delay does not work if you opted to hide the splash screen when any AWT window opens. In that case, the Show splash for box is disabled and the SPLASHMINTIME equation is ignored.

If a delay is set, the splash works as follows. It appears at application startup and stays on the screen for the specified time. After that, the selected "auto hide" policy has effect. If the window has been already opened, the splash disappears; if not, it remains on the screen until the respective window will be opened.

Finally, you may choose whether to hide the splash screen if user clicks on it. By default, user click hides the splash screen for Java 5 applications, but does nothing for Java 6 applications. If you wish the splash screen to disappear on user clicks for Java 6 applications as well, do the following: