Super Prev Next

Application considerations

Super Prev Next

Implementation-specific differences between JVMs

Excelsior JET implements all features of the Java programming language and Java SE platform according to the respective specifications. However, certain applications exploit Java features not enforced by the specifications. Such applications may fail to run on the JET Runtime, and probably on some other JVMs too.

This section lists the known implementation differences between Excelsior JET and HotSpot, a VM implementation included with OpenJDK. You are encouraged to remove all possible usages of implementation-biased features not enforced by the Java specification.

Super Prev Next

VM vendor

The first obvious distinction is that the java.vm.vendor system property has a different value. Surprisingly, certain third-party Java components use it to determine the "capabilities" of the underlying JVM.

How to fix: You may try to find the latest versions of such components, which may have been improved to work with a larger set of Java SE VMs.

Super Prev Next

Order of reflected methods and constructors

The elements of arrays returned by Class.getDeclaredConstructors() and Class.getDeclaredMethods() are not sorted and are not in any particular order.

This is exactly what the Java SE API specification says rather than a feature of Excelsior JET. Nevertheless, certain third-party Java components try to exploit a particular order of reflected class members.

How to fix: You may try to find the latest versions of such components, which may have been improved to work with a larger set of Java SE VMs.

Super Prev Next

Deprecated methods of class Thread

Thread.stop() has no effect unless the thread is waiting on an object. Thread.suspend() may provoke a deadlock in the JET Runtime.

Note that Thread.stop(), Thread.suspend(), and Thread.resume() are deprecated methods. Specifically for Excelsior JET, it is strongly recommended to rewrite the code that uses these deadlock-prone methods.

How to fix: A detailed explanation and recommended replacements are given in the article "Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?" available at

Super Prev Next

Eager class resolution

When compiling a Java application, the JET Optimizer tries to resolve almost all references from each class to other imported classes. On the contrary, HotSpot exploits lazy class resolution, that is, a reference to a class is resolved only when it is first used. Both resolution policies are allowed by the Java specification.

Excelsior JET simulates lazy class resolution for the known classloaders that rely on it systematically, such as the Eclipse RCP (OSGi) classloaders. But in general, such reliance in the application code may cause subtle side-effects and often leads to the creation of fragile code. It is better to avoid making speculative assumptions on when a particular class will be loaded.

Super Prev Next


JVM Tool Interface (JVMTI), an optional part of the Java SE platform API, is not supported in Excelsior JET due to security reasons. Its implementation would enable a wide variety of introspection techniques for the compiled applications, which is highly undesirable.

Super Prev Next

Limited support for Java instrumentation agents

Despite the JET Runtime recognizes the -javaagent option, it takes no effect on pre-compiled classes. Thus, instrumentation is done only for the classes loaded by JIT compilers that come with the JET Runtime Mixed Compilation Model.

Super Prev Next

No class/jar files

To provide code protection, the original class/jar files are not deployed with the compiled application, and therefore, are not available at run time. If the application tries, for example, to compute a check sum of a class by reading its content with conventional file system operations, it would fail.

Workaround: You may configure the JET Optimizer to make the required jar file available to the compiled application, provided they do not contain the code you wish to protect from decompilation. For more details, see section Resource packing.

Note: Some applications, such as the javac compiler, need only symbolic information from class files and do not use the contained bytecode instructions. In such cases, everything should work without any workarounds.

Super Prev Next

Standard Exception Messages

Detailed messages of the exceptions thrown by the JVM, such as IndexOutOfBoundException, may differ from those of HotSpot.

Super Prev Next

Stack trace

By default, Throwable.printStackTrace() methods omit line numbers and names of some methods in call stack entries, but class names are exact.

Workaround: You may enable full stack trace printing as described in section Stack trace.

Super Prev Next

Default heap size

If you do not set the maximum heap size, the JET Runtime determines it adaptively depending on the allocation profile and amount of available physical memory as described in section Memory management.

The HotSpot JVM uses different heuristics to set the default maximum heap size. For more details, see

Workaround: You may set the maximum heap size explicitly (see Memory management.)

Super Prev Next

Signed jars

As, by default, the application jar files are not deployed with the compiled executable, checking digests of the signed jars fails.

Workaround: You may configure the JET Optimizer to make the signed jars available to the compiled application as described in section Resource packing.

Note: In such case, the jars will probably be used only for checking the signatures which does not help ensure the authenticity. For that purpose, it would make more sense to sign the compiled executable using a third-party utility.

Super Prev Next

Non-standard VM options

Most -XX options are not supported as they are specific to a particular implementation. Moreover, certain -X options are not supported too, for example setting -Xbootclasspath takes no effect. The list of the supported VM options is given in section VM Options.

Super Prev Next

Endorsed jars

If your application uses Endorsed Standards Override, it is not enough to specify the java.endorsed.dirs system property as you do when using the HotSpot JVM. To enable the override mechanism, you need to use the JET Setup utility to create a new JET profile including the endorsed jars. For more details, see Profiles.

Super Prev Next

Runtime Selection

Note: Information in this section is not applicable to the Standard Edition of Excelsior JET.

Excelsior JET VM comes with multiple implementations of the runtime system, optimized for different hardware configurations and application types. It enables your application to effectively utilize the computing power of systems that support parallel execution /Examples are multi-processor servers, multi-core chips and CPUs that support Hyper-Threading Technology/ , thereby improving performance.

This section describes the available runtime systems and helps you select the proper runtime for your applications and target system configurations.

Super Prev Next

Available runtimes

Super Prev Next

Desktop Runtime

The Desktop Runtime is suitable for applications that typically run on conventional desktop and notebook computers. It is optimized for single-CPU systems, including those based on multi-core chips. This is the best choice for rich clients, visualization and engineering design tools, and other desktop applications.

Super Prev Next

Server Runtime

The Server Runtime fits best for highly concurrent server applications. It provides out-of-the-box performance and scalability and takes full advantage of the computing power of multi-processor hardware. In particular, the Server Runtime includes the CoreBalance garbage collector that fully utilizes parallel hardware to reduce average and maximum pause time. Note that Excelsior JET Enterprise and Embedded Editions are the only retail version that include the Server Runtime.

Super Prev Next

Classic Runtime

The Classic Runtime is designed to use on low-end hardware which does not support parallel execution such as uniprocessor systems equipped with old CPU models of the x86 architecture. It is not recommended for use on HyperThread/multi-core CPU and multi-processor systems.

Note that the Classic Runtime is the only option in the Standard Edition of Excelsior JET.

Super Prev Next

Which runtime fits best for my application?

Basically, you select an Excelsior JET Runtime depending on the type of your application and hardware configurations of the systems to which it will be deployed. To make the right choice, follow the recommendations below.

Super Prev Next

Server-side applications

If your server application will be deployed to multi-processor machines, opt for the Server Runtime. Other Runtimes are not optimized for N-way systems so choosing them would significantly degrade throughput of server applications.

If your server application requires most efficient garbage collection, Server Runtime is the best choice to run on any parallel hardware, e.g. multi-core chips.

Super Prev Next

Client-side applications

The Desktop Runtime is the optimal choice for desktop applications running on single-CPU systems.

Note that using the Classic Runtime on the systems that support parallel execution, ranging from Intel P4 powered by the Hyper-Threading technology to Intel Core and up, may cause significant performance degradation.

If your application needs most efficient garbage collection, Server Runtime, featuring CoreBalance GC, will work better on modern multi-core CPUs as compared to the Desktop Runtime.

Super Prev Next

Embedded applications

If your embedded platform is equipped with a CPU that does not support parallel execution /For instance, a Pentium II-class processor/ , the Classic Runtime fits best. Otherwise, use the Server Runtime.

You may experiment with each runtime flavor as described in the next section.

Super Prev Next

How to enable a particular runtime

You select the runtime when compiling your application. The JET Control Panel shows the available RT options on the Target page. If you use the command-line interface to the JET compiler, specify the JETRT equation in the project file:


You may also select the runtime at application launch time specifying the jet.rt system property (see Setting System Properties). For example, to enable the Classic Runtime, specify


The valid values are classic, desktop, and server.

Note, however, that the jet.rt property can only force lower-end runtimes /In the sense of this order: Classic < Desktop < Server/ than the runtime selected at compile-time. For instance, if you chose the Desktop Runtime when compiling your application, you may force the Classic Runtime during its launch, but not the Server Runtime. If you wish to test your application against all runtimes, enable the Server Runtime when compiling and then select other runtimes using the jet.rt property as desired.

Finally, if you run your application via the xjava launcher, use the -Xrt option to select the desired runtime (see Options):

    xjava -Xrt=server -jar MyServer.jar

Super Prev Next

Code performance

If you used any optimizing compilers before, you must have experienced a situation when a particular combination of the many available optimization control options results in incorrect code being generated by the compiler for your program, or when the program only works properly when compiled with debug information generation enabled. The reason is that a compiler with dozens of optimization control options is extremely difficult and expensive to test, as the compiler manufacturer has to check all possible combinations of options, so no vendor does that.

Fortunately, this is not the case with JET. Unlike many other compilers, JET always optimizes code to the maximum extent possible. Even enabling generation of debug information to ease field engineering does not affect the output code. The only two optimizations that may be disabled or adjusted are stack allocation of objects and inline expansion of methods, because they can negatively affect scalability (see Number of threads) and code size of the resulting program.

To get the maximum performance, do the following:

  1. Enable stack allocation of objects: Stack allocation is enabled by default. See Optimizations and Number of threads for more information.
  2. Enable inline expansion of methods: See Optimizations and also comments below for details.

Inline expansion should be used with care. It allows the compiler to substitute a method in-line, if that method is declared as final or if compile time analysis confirmed safety of such substitution. As a rule, enabling inline expansion results in faster but bigger code. However, the effect of this optimization depends on the programming style (sizes of methods, etc). You may control inlining aggressiveness using equations INLINELIMIT and INLINETOLIMIT in the project file, or by selecting one of the presets in the Inline expansion list in the Control Panel.

Super Prev Next


Super Prev Next

Multiprocessor systems

Excelsior JET is fully SMP-aware, so your parallel applications will scale to multiple processors. However, you should select the Desktop or Server Runtime to enable the most effective utilization of several CPUs (see Runtime Selection). You may wish to fine tune the garbage collector as described in Parallel hardware.

Super Prev Next

Number of threads

Excelsior JET runtime maps Java threads directly onto native operating system threads. Windows reserves the same amount of address space for the stack of each thread of a particular process, which is retrieved from the size of stack reserve field of its EXE header.

The default size of stack reserve is about one megabyte, which basically means that if your program attempts to run 1,000 threads simultaneously (which is not unusual for server-side applications), their stacks will claim one gigabyte of the process’ virtual address space, of the total of four gigabytes. Given that some part of the virtual address space is reserved by the operating system (Windows reserves half of it, i.e. 2GB), one process cannot run more than a few thousand threads simultaneously with that default setting.

An attempt to run too many threads simultaneously in a Java application results in OutOfMemoryError. Waste of address space for thread stack reserves also effectively limits the amount of memory that the memory manager may allocate from the OS and thus may also cause OutOfMemoryError.

To reduce the default stack size and thus improve the scalability of your application with respect to the number of threads:

This is equivalent to setting the -Xss option of the standard Java launcher.

Another thing to consider is that enabling stack allocation of objects increases stack size requirements of the compiled applications, which may negatively affect scalability. Therefore, you may wish to disable this optimization by unchecking the Allocate objects on the stack box on the Options page (see Optimizations) or turning the GENSTACKALLOC option off in the project file. This would enable you to further reduce the thread stack size as described above, thus letting your application run more threads simultaneously at the cost of minor performance loss.

Super Prev Next

VM Options

The JET Runtime recognizes the following standard and HotSpot-specific VM options:

Super Prev Next

Sources of VM Options

The JDK Java application launchers receive VM options as command-line parameters:

    java -Xmx2g -Dproperty=value MyAppMainClass arg1 arg2

However, after native compilation the same Java application becomes a conventional executable file that does not need any launchers, so all its command-line arguments are passed to the main method of the main class:

    MyApp arg1 arg2

As you may see, there is no place on the command line to set a system property or specify a VM configuration option, unless you’ve built a multi-app executable. Here is how Excelsior JET addresses this problem in the general case:

First of all, it is possible to "hardwire" VM options into the executable during compilation (see Setting Java system properties), packaging (see Editing Java system properties and Assigning VM properties), and/or installation (see xbind).

Now, if there are any system properties that must be always set for the given application to work properly, it makes a lot of sense to hardwire them into the executable at compile time. You may also provide safe defaults for certain VM settings. But it may also be desirable to set or adjust the values of some options, such as the Java heap size, at install time, based on the particular target system configuration. The problem is that changing the executable at install time invalidates its digital signature and may raise the attention of real-time antivirus software.

Furthermore, you may also want to enable the end user or the system administrator to change certain VM options after installation, e.g. set a system property that enables debug mode. At that point, modifying the executable is usually out of the question.

Therefore, after reading the hardwired VM options, the JET Runtime proceeds to query the following sources:

The JET Runtime queries these sources in the above order, merging all options; in case of duplications, the most recently obtained value prevails. This enables you, for instance, to override the value of a hardwired systems property in a VM options file.

Notice: An Invocation DLL may also receive VM options via the vm_args parameter of the CreateJavaVM() JNI call. The JET Runtime merges those options with the hardwired set before querying the above sources.

Super Prev Next

VM Options Files

New in 15.3:

After retrieving the hardwired VM options from the application binary, the JET Runtime looks up two files in the directory where the process executable resides: a local VM options file called simply jetvmprop /"jetvmopts" or "jetvmoptions" would have been a better name, but we decided to maintain consistency with the name of the legacy environment variable serving the same purpose./ and then an executable-specific VM options file called executable-name.jetvmprop /Mind the difference: MyApp.exe on Windows would look for MyApp.jetvmprop, whereas MyApp.bin on Linux/macOS would try to open MyApp.bin.jetvmprop./ . Both are plain text files in the default platform encoding. Each line of a valid JET VM options file is either blank, contains one VM option, or begins with a hash sign (#) that indicates a comment. Leading and trailing whitespace is ignored.

The presence of either file is strictly optional. No error condition is triggered if one or both are absent. If both the local VM options file and the executable-specific one exist, the local one is parsed first.

You can disable parsing of VM options files altogether by setting the compiler option IGNOREJETVMPROPFILES ON.


    # For the sanity of future maintainers, write comments

    # Without these settings, the app throws an OutOfMemoryError:

    # Uncomment to collect data for Excelsior Support:
    #    -Djet.gc.stat
    #    -Djet.jit.loud

    # Spaces and other interesting characters are passed as-is.
    # There is no need to use quotes or escapes:
    -Dapp.home.dir=C:\Program Files (x86)\App Company\The App

        # This is also a comment (leading whitespace is ignored)

    # IMPORTANT: All inner whitespace is PRESERVED!
    # This sets the property "happy debugging  " to "  true":
    -Dhappy debugging  =  true

    # Unrecognized VM options are silently ignored!

The above file instructs the JET Runtime to merge the following options into the (possibly empty) set of options that it has retrieved earlier:

    "-Dapp.home.dir=C:\Program Files (x86)\App Company\The App"
    "-Dhappy debugging  =  true"

Super Prev Next

The JETVMPROP Environment Variable

Warning: Use with caution! Never set this environment variable globally (i.e. in the Windows registry, user login script, or the Group Policy Preferences), especially on enduser systems, as that may cause other JET-compiled applications installed there to fail or misbehave.

Before version 15.3, the JETVMPROP environment variable was the only universal /Multi-app executables and the JNI CreateJavaVM() function have their own in addition./ mechanism for passing VM options to a native executable at launch time. It is intended for use during development and field engineering.

Normally, you would either hardwire the major options and necessary system properties into the executable at compile, packaging, or install time as described in Setting Java system properties, Editing Java system properties / Assigning VM properties, and xbind, respectively, or use a VM options file. Should you need to override or add to the hardwired settings, but have no write access to the directory containing the application executable, create a small batch file that would set the JETVMPROP environment variable and then launch your application:

    SET JETVMPROP=-Xverify:all -Djet.gc.threads=2
    MyApp %*

Note: The VM options retrieved from the JETVMPROP environment variable are merged into the set that already includes the hardwired options and options read from VM options files, if any. If a particular option appears to be already set, the value retrieved from the environment variable prevails.

You can also force your application to ignore the JETVMPROP environment variable altogether using the IGNOREJETVMPROPENVVAR compiler option.

Super Prev Next

JET Runtime-specific System Properties

The JET Runtime recognizes the following properties during VM initialization:


Sets the maximum heap size to the given amount of bytes (kilobytes, megabytes, or gigabytes respectively, if either of the suffixes k, m or g is present), overriding the compile-time heap size setting. Setting size to zero enables adaptive heap sizing. See Memory management for more information.


Specifies the maximum proportion of CPU time to be allocated to the garbage collector at run time, in 1/1000ths. See GC ratio for details.


Select a specific JET Runtime. Valid values of flavor are classic, desktop, and server.

See Runtime Selection for details.


Sets the maximum number of concurrent threads that may be used for the CoreBalance garbage collector available in the Server Runtime. By default, N equals the number of processors/cores on the system. See Parallel hardware for more information.


This option is specific to 64-bit version of the JET Runtime. It defines the amount of address space reserved for code and data produced by the JIT compiler. The default value is 1 gigabyte and the maximum value is 2 gigabytes.


Logs names of DLLs loaded by the application at run time into a file.


Enables or disables the stack backtracing facility. By default, it is enabled. See Stack trace for more information.


Speicifies a custom error message for a JET Runtime crash. For more details, refer to section Customizing Runtime error messages.


Enables collection of profile data during application execution. For more details, refer to section Collecting profile.

Specifies the name of the execution profile data file created when jet.profiler is set. For more details, refer to section Collecting profile.

Forces the JET Runtime to attempt changing the current directory to the value of the standard user.dir system property during initialization. This is essentially a workaround for applications that have to be started from a particular directory, usually the directory containing the application binary, in scenarios where satisfying that condition is not possible. Notable examples are Windows services , which always start from the system directory, and Apple macOS application bundles — the rules for setting the current directory at bundle startup are inconsisent from one operating system version to another.

99% of the time, you would also set the user.dir property to a special value *{exe.dir} that denotes the directory containing the application binary:


Super Prev Next

Setting System Properties

You can pass system properties to your optimized Java application using the standard VM option "-D". There is a number of ways to set VM options, recommended for different usage scenarios:


Super Prev Next

Memory management

Excelsior JET lets you define the policy of memory management to be used for your Java application at run time. This section describes a few simple mechanisms that you can employ to set an optimal balance between performance of the application and its memory footprint.

Super Prev Next

GC ratio

Ideally, an application should work fast enough and consume as few memory as possible. In practice, there are always trade-offs between application performance (or throughput) and its memory footprint. What’s especially important is that performance and memory requirements are application-specific. For one program, performance is critical, whereas low memory footprint has more value for the other. Put simply, one size does not fit all.

Fortunately, the JET Runtime lets you fine tune the performance/memory balance for your Java application. For that, you just set a ratio in which the Runtime will portion out execution time between the two tasks: execution of the application’s code and garbage collection. This technique is simple and effective:

You can do that by specifying the GC ratio setting to the JET Runtime. Its value is the tenths of percent of total CPU time that may be spent for garbage collection. For example, the default GC ratio is 1.1% which means that GC will normally take the percentage in total execution time. You can vary the GC ratio as follows.

The maximum GC ratio you can set is 40.0%.

Note: changing the default GC ratio is not available in the Standard Edition of Excelsior JET.

The default setting (1.1%) is biased to performance and, therefore, may cause excessive memory consumption in some cases. You can experiment with your Java application by fine tuning the GC ratio. Often, increasing the value by several units may noticeably reduce memory footprint. That’s why the unit of measure is 1/10th of percent not a whole percent.

One might question: what reduction in memory footprint can I expect when increasing the GC ratio by X%? In general, it depends on two factors: how much garbage your application produces and how fast it does that. Thus, the answer is specific to a particular application.

Note that under certain circumstances, the JET Runtime is unable to meet the GC ratio requirement. For example, if a Java application allocates objects very intensively and amount of available physical memory is low, more CPU time may be spent in the garbage collector regardless of the ratio specified.

Finally, you may set the GC ratio to 0 to entirely disable the mechanism (it’s not recommended, though.) In such case, GC is automatically invoked only if the JET Runtime is unable to serve a regular request for object allocation due to memory constraints as described in the following sections.

Super Prev Next

Maximum heap size

You may specify the maximum amount of heap memory that your application is allowed to allocate at run time /The respective command line parameter of the standard Java launcher is -Xmx/ :

To override the compile-time setting, you may set the system property at install time or even at launch time (see Setting System Properties).

You may need to specify the maximum heap size if you do not want the Java heap to exceed certain upper bound in any case. On the one hand, it may be useful to reduce application memory footprint. On the other hand, it may compromise performance of your application. For example, it might work more effectively when using large Java heaps on the target machines that have high RAM capacity.

The default value of the maximum heap size is 0 which means Adaptive, that is, heap size is bounded by a fraction of RAM capacity of the target system /If you use 32-bit version of Excelsior JET, the Java heap is most probably bounded by the size of Virtual Address Space that varies from 2 to 4GB, depending on the underlying operating system./ . Note that it does not mean that your application will necessarily take gigabytes of memory at run time. First, the JET Runtime checks the GC ratio which effectively damps inflation of the heap. Moreover, the runtime constantly monitors the amount of available physical memory as described in the next section.

Super Prev Next

Handling low memory

As a rule, it’s hard to determine the "right" application memory settings because they are specific to a particular target system. For instance, you consider a box equipped with 4GB of RAM as a "typical target system" but some customers are proved to be still using 2GB machines. Another example is a system under heavy workload: imagine that your application runs simultaneously with a couple of other programs hungry for memory. Anyway, your application must work, more or less efficiently.

To address these problems, the JET Runtime considers the amount of available physical memory in the system to schedule garbage collection. If low memory is detected, GC is activated to avoid unnecessary swapping RAM pages to the hard disk. Of course, it leads to more frequent GC invocations and penalizes application performance. But it’s a good alternative to tremendous overheads of swapping memory to and fro.

However, if the runtime detects that application execution has degraded to sole garbage collection or it’s unable to allocate an object even after GC invocation, the physical memory boundary is crossed. The JET Runtime augments the Java heap with the amount of memory enough to serve the allocation request plus some decent gap necessary for further operation. Often, this move helps clear the air. The operating system reacts to the event and fetches memory, e.g. from the system cache, so that the application continues running smoothly.

You have control over the JET Runtime with respect to crossing the physical memory threshold. To override the default behavior

As a result, OutOfMemoryError will be thrown instead of using virtual memory to increase the heap. This mode is useful if you suspect that your application has performance issues due to not enough memory in the system. You may easily prove or disprove that by disabling the default policy and handling OutOfMemoryError exceptions, if any.

Super Prev Next

Large heaps on 32-bit systems

If you use 32-bit version of Excelsior JET, the theoretical limit of the heap size for compiled applications is 4 gigabytes. In practice, however, a part of the virtual address space is occupied by the operating system, thread stacks, program executable and dynamic libraries, etc. As a result, the application cannot allocate a multi-gigabyte heap even if the system has enough physical memory.

The upper bound of the maximum possible heap size is O/S-dependent. If you run a JET-compiled application on 64-bit Windows or Linux, it is able to allocate more than 3GB of heap memory without hassles. However, care must be taken if the system requirements of your Java application include 32-bit Windows and/or Linux flavors. Typically, all the systems allow allocation of a 1.5 GB heap out-of-the-box provided the machine has enough RAM. This can be considered as the “largest common denominator”.

Certain 32-bit operating systems, e.g. Windows 2003 Server, can be configured to enable allocation up to 3 GB heap as well. For more details, refer to

In addition, some Linux distros provide an option to build the kernel in a special mode that makes approx. 4GB address space available to the process. For example, RedHat Enterprise Linux 3 and higher include a kernel known as the hugemem kernel. Note that this incurs some overhead when transferring from user to kernel space, e.g. in the case of system calls and interrupts.

Super Prev Next

Parallel hardware

If your target systems have multiple CPUs, or support parallel execution via multi-core or HyperThread technologies, select the appropriate version of the JET Runtime as described in section Runtime Selection. The right choice of Runtime has a great impact on performance of applications that use the Java heap intensively.

Moreover, on the parallel hardware, the CoreBalance garbage collector available in the Server Runtime, runs in multiple threads to reduce collection pauses. By default, the total number of working GC threads is equal to the number of CPUs/cores reported by the operating system. However, you may reduce this number for optimum system performance, e.g. if you want one or more CPU cores to be available to some native threads or processes running at the same time.

For that, set the value of the jet.gc.threads property to the maximum number of GC threads. For instance, to make the garbage collector use at most two threads, specify the following setting:


Note: the CoreBalance garbage collector is only available in the Enterprise and Embedded Editions of Excelsior JET.

Super Prev Next

Multi-app executables

Note: Information in this section is not applicable to the Standard Edition of Excelsior JET.

Excelsior JET may compile more than one application into a single executable and let you select a particular application at launch time via command line arguments. This enables you to:

You enable the multi-app mode:

Super Prev Next

Command-line syntax

The command line syntax of multi-app executables is an extension of the java launcher command line syntax that allows specifying the main class, VM options, Java system properties, and the arguments of the application:

    Exe-name [Properties-and-optionsMain-classname [App-arguments]

For example,


Runs the multi-app executable with as the main class.

MyApp -Xmx256m -Dmy.prop=val

Runs the multi-app executable with the specified main class and sets a runtime option (maximum heap size) and a Java system propery.

MyApp -Xmx256m -Dmy.prop=val 10 1

The same as above but also specifies two application arguments.

Note: If the specified main class does not exist, NoClassDefFoundError is thrown and the application terminates.

Super Prev Next

Default main class

When you simply run a multi-app executable without arguments, the main class and Java system properties set at compile-time will be used.

If you need to specify command line arguments or system properties for the application without changing the default main class, use the following syntax:

    Exe-name [Properties-and-options] [-args App-arguments]

Here go a few examples of the well-formed command lines:

MyApp -args 10 1

Runs the multi-app executable with two application arguments.

MyApp -Xmx256m

Runs the multi-app executable with no arguments and sets a runtime option (maximum heap size) and a Java system properyy

MyApp -Xmx256m -args 10 1

The same as above but also specifies two application arguments.


  1. Certain options supported by the standard java launcher may be also specified on the command line of multi-app executables. You may find the list of such options recognized by multi-app executables in section VM Options. Note that some irrelevant options such as -cp, -jar, -Xbootclasspath are not supported and will be ignored.
  2. On application startup, the VM options specified on the command line are merged into the set of options it retrieved from other sources. The command-line settings have maximum priority.

Super Prev Next

Windows services

You may build a multi-app executable runnable as both plain application and Windows service. The recommended procedure is as follows:

  1. create a new project as Plain Java SE application (see Starting Excelsior JET Control Panel)
  2. compile the application with the multi-app executable option enabled
  3. convert the type of the project to Windows service by selecting the Project/Convert to... item of the main menu.
  4. make the necessary settings for Windows service as described in Chapter Windows services.

Actually, you may first create the Windows service project and then convert it to Plain Java SE application in the same manner.

When packaging the executable, the JetPackII tool will automatically recognize that the executable may be installed as a Windows service and prompt you to make the necessary installation settings.

Note: If you use a third-party installation program rather than Excelsior Installer, you should care about installation of the service in the system (see Service installation and removal). In such case, specify the -Xservice option in the Properties-and-options section of the command line. Optionally, you may also set the service name as -Xservice:Service-name to register the service in the system under that name /By default, the service name selected at compile time (see Executable settings) will be used./ . Also, remember that the main class, if specified, must extend com.excelsior.service.WinService as described in Chapter Windows services.

Keep in mind that Excelsior Installer automatically adds the -Xservice option to the arguments of a multi-app executable installed as a Windows service. Therefore, you do not need to specify it explicitly in such case.

Super Prev Next

Splash screen

If the application compiled as a multi-app executable has a splash screen and you need to suppress it, e.g. when running the executable with a main class other than the default, specify the -Xnosplash option in the Properties-and-options section of the command line.

You may also wish to replace the pre-configured splash screen image with another one. To do that, use the -splash option specifying the pathname of the desired image, for example

MyApp -splash:another-splash.gif

Note: If the multi-app executable is run as a Windows service, the splash screen is suppressed automatically.

Super Prev Next

Disk footprint

Note: Information in this section is not applicable to the Standard Edition of Excelsior JET.

With Excelsior JET, you can optimize disk footprint of your Java application, that is, reduce the amount of disk space required by the application installed on target systems. This can be useful if the application files should be placed into flash memory, which is a typical requirement for contemporary embedded systems. Another use case is running a Java application off a USB flash drive without installation.

Excelsior JET includes the Global Optimizer that performs static analysis and uses the profile information collected during Test Run to figure out what application and library classes are rarely used or not used at all during execution.

The idea behind the saving of disk space is not to compile the classes that will unlikely be loaded at run time: such class files are compressed when creating the installation package and then installed in a compressed form on the target system. This technique helps reduce disk footprint dramatically with a minimal impact on application start-up time and performance in most cases.

If, however, the application tries to load a class placed into the compressed bundle, the JET Runtime inflates (a part of) the bundle to access the requested class transparently to the running application. This technique is called on-demand decompression.

There is a trade-off between the effectiveness of disk footprint reduction and possible overheads that on-demand decompression may impose. You have two options to balance the overheads as described below.

Super Prev Next

Medium reduction

The medium reduction method saves up to 15 MB of disk space. If on-demand decompression occurs, the JET Runtime inflates only a part of the compressed bundle to get the requested class file. As a result, this reduction method has little impact on start-up time/performance and does not increase memory usage.

Super Prev Next

High reduction

The high reduction method saves up to 30 MB of disk space using so called solid compression. That is, if on-demand decompression occurs, the entire bundle is inflated and temporarily stored to make its contents available to the Runtime.

Note: inflating the highly compressed bundle takes up to several seconds and thus pauses application execution until the data are decompressed. Refer to section On-demand decompression that describes how to achieve non-disruptive execution.

Two techniques of storing the uncompressed data are implemented:

You can choose the method of disk footprint reduction appropriate to your application using the JetPackII tool. When creating the installation, select the desired options in the Disk footprint panel on the Runtime page.

Super Prev Next

Complementary methods

In addition to enabling the compression of unused classes, you may exclude optional components of the JET Runtime from the resulting installation (see Step 3: Configuring the JET Runtime.)

Another possibility is tuning the compiler options that control the executable size. The major effect can be achieved by setting the "Low" or "Tiny methods only" policy for the inlining optimization (see Method inlining for details.)

These methods help you further reduce disk footprint of your optimized Java applications.

Super Prev Next

On-demand decompression

If you opt for the high reduction of disk footprint, on-demand decompression of the entire bundle may occur during application execution. Note that it happens only if the Global Optimizer could not detect all classes that are used at run time and some of them were placed into the compressed bundle when creating the installation.

Before deployment of your application to target systems, you can check whether the decompression occurs at run time. For that, test your application launched from within JetPackII on the page Trial Run. If the decompression has occurred, JetPackII displays a warning after completion of the trial run.

If you want to eliminate the decompression overheads, you should assist the Global Optimizer by providing a more complete profile information. To do that, open the project in the JET Control Panel and perform the test run step to repeat the same testing scenarios you used when running the application from within JetPackII.

Moreover, if there are automatic tests for the application, e.g. code coverage or stress tests, you can perform the test run without invoking the JET Control Panel as described in section Performing a Test Run.

As a result, the profile information will be automatically completed and you can then re-compile your application with the Global Optimizer enabled. To learn more about why the test run is required, refer to section Why Test Run is necessary.

If, due to some reasons, the performing of a exhaustive test run is not feasible for your application, you can select the medium reduction method to avoid possible overheads of on-demand decompression.

Super Prev Next

Creating trial versions

Note: Information in this section is not applicable to the Standard Edition of Excelsior JET.

You can create a trial version of your Java application that will expire in a specified number of days after the build date of the executable or on a fixed date /The setting of fixed date expiration is available only though the command line compiler./ . It means that you will need to update the download file of your application from time to time. In return, the end user will not be able to bypass the license check by changing system date at install time only /To bypass the check, one should keep a back date in the system as long as your application is active. This is very inconvenient because it may provoke issues in your and/or other applications running at the same time./ . As the evaluation period is over, the application no longer starts and shows the expiration message you specified when compiling it.

You enable creation of the trial version as follows:

To specify the expiration message do the following:

You may use the control sequence \n in the message to display the following text on a new line.

Super Prev Next

Application appearance

To customize the appearance of your application, you can

You may control these features at compile time using either JET Control Panel or command line interface to the JET compiler as described below.

Super Prev Next


To associate an icon with the resulting executable, do the following.

Super Prev Next

Console window

By default, the standard input/output/error streams are enabled to let the application print messages to the console. As a result, when starting your GUI application, you see a black console window opened in addition to the application’s frames. If you do not want the window to appear, you can suppress it /With OpenJDK, you would use the javaw launcher for that./ for the application:

Super Prev Next

Splash screen

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

Super Prev Next

Specifying a splash image

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 a required format using a third-party image processing tool.

Super Prev Next

Stack trace

The JET Runtime supports three modes of stack trace printing: minimal, full, and none.

In the minimal mode (default), line numbers and names of some methods are omitted in call stack entries, but class names are exact.

In the full mode, the stack trace info includes all line numbers and method names. However, enabling the full stack trace has a side effect of substantial growth of the resulting executable size by approximately 30%.

In the none mode, Throwable.printStackTrace() methods print a few fake elements. It may result in performance improvement, if the application throws and catches exceptions repeatedly. Note, however, that some third-party APIs may rely on stack trace printing, for example, Log4J API that provides logging services.

Super Prev Next

How to select stack trace mode

In the JET Control Panel, you select the desired stack trace mode on the Target page (see Stack trace support).

You may also select the stack trace mode via compiler options and run-time properties. To enable the "none" stack trace mode, set the value of property jet.stack.trace to false:


To enable the full mode, keep the default jet.stack.trace option value, toggle the GENSTACKTRACE option ON in your project file


and re-compile your application.

Super Prev Next

How to disable stack trace

For security reasons, you may wish to completely disable stack trace output in the end-user version of your application. To do that, set the option DISABLESTACKTRACE ON in your project file:


Super Prev Next


In a JVM, assertions are disabled by default, but may be enabled for the entire application or for particular classes at launch time using the java command’s switches -ea, -da, -esa, and -dsa. With JET, if you enable assertions using the same switches in the JETVMPROP equation in your project file:


or control them at launch time using the JETVMPROP environment variable:

    SET JETVMPROP=-ea:com.MyCompany.MyPackage

JET also supports enabling and disabling assertions programmatically at run time.

Super Prev Next

Resource packing

A typical Java application consists of classes that contain the application’s code, and resources such as images, icons, property files, which the application loads at run time.

If the resource files are placed into one or more jar files, the compiler packs the resources into the resulting EXE or DLL, almost like that is done for native applications. The JET Runtime will read the resource files during execution and use them as if they were separate files. No changes in your application’s code are required to make this technique work.

Using the JET Control Panel, you may enable/disable resource packing for particular jars as described below.

Super Prev Next

Resource packing modes

When compiling a Java application, the JET Optimizer processes each jar file listed in the classpath and, depending on the project settings, may pack the contained resource files into the resulting executable.

For jar files, the Optimizer supports the following resource packing modes:

  1. Auto-detect: pack resource files and non-compiled classes /Non-compiled classes may appear if you enable selective optimization for this classpath entry. For more details, see Code protection/ , if any. This way, all jar contents is either compiled or packed, so the original jar file is no longer required for running the application.

    This is the default mode for the jar files included in the project.

  2. None: do not apply resource packing to this classpath entry. In this mode, neither class files, nor resource files are packed into the executable. The jar file should be distributed along with the application executable.

    For example, suppose you develop a Java application extensible with plug-ins. You may disable packing the plug-in jars and distribute them along with the executable. As a result, client installation of your application can be updated by replacing the jar files, for example, with newer versions of the plug-ins. Note that the JET Runtime will JIT-compile the classes from the jar files.

  3. Original jar/zip: pack the entire jar/zip file, including all resources and classes.

    For example, consider a Java component whose implementation requires presence of the original class files at run time. For instance, Java Crypto Extensions also known as security providers check the sizes of their class files during execution. In such cases, the class files serve as both program code and resources. Therefore, despite all the classes are pre-compiled, you have to make them available to the running application. Packing such jar files as a whole resolves the problem.

Note: Excelsior JET does not support the packing of resource files that reside in directories. /With an exception for Tomcat web applications (see Step 3. Settings for Web applications)./ The reason is that directories are writable, that is, the application may overwrite resource files at run time, so packing them into the executable may change behavior of the program.

If your application really overwrites resource files at run time, you should deploy that directory along with your executable and ensure the directory is included in the application classpath. For more details, see Step 2: Configuring Resources And System Properties.

Otherwise, you may place all classes and resources from the directory in a jar file and add it to the classpath. As a result, the JET Optimizer will compile the jar file in the default mode of resource packing as described above.

Super Prev Next

Setting resource packing options

To change the default settings, open your project file with the JET Control Panel, and go to the Classpath page. The central area of the page is occupied by the classpath grid. Each row of the grid corresponds to a single classpath entry — a directory or jar file. The last column named Pack into exe, specifies the resource packing mode for each entry. Click the cell, and select the appropriate value from the drop-down list.

If you edit project files manually, use the PACK equation to control resource packing. Refer to the JC reference chapter for more details.

Super Prev Next

Character encodings

When creating a profile, JET precompiles the Java SE classes that are needed for input and output of characters in national encodings into a set of DLLs. The idea is to place support for rarely used encodings and encodings that require large conversion tables (such as Chinese) into separate DLLs, so as to reduce the disk footprint of compiled applications that do not use some or all of those encodings.

If your application may need to use national encodings, make sure to include the respective locales into the installation package as described in Selecting optional components.

Super Prev Next

Bytecode consistency checks

On a virtual machine, if a certain class is imported but never used during program execution, i.e. it is never instantiated, none of its static methods are called, and none of its static fields are accessed, then no attempt to load that class would occur and therefore the program would execute normally even if the respective class file is not present on the system or cannot be reached by the VM.

Similarly, if a class does not contain a particular method or field that is referenced in another class, execution on a virtual machine would fail only when and if control reaches the code referencing that absent field or method.

Being an ahead-of-time compiler, Excelsior JET analyzes the entire compilation set and thus is able to detect such inconsistencies. By default, they result in compilation errors. However, when an inconsistency is detected in bytecode that is not under your control, such as a third-party class library, you usually do not have a chance to remedy it quickly. If you encounter such problem, contact the vendor who supplied the inconsistent bytecode, and toggle the respective JET options to make the compiler treat bytecode inconsistencies as warnings:

Note: In some applications, imported classes unavailable at compile time become available at run time. JET may handle this situation properly if you enable the reflective shield facility of the Mixed Compilation Model.

Super Prev Next

Baseline compilation

In some cases, the main JET compiler may fail to compile a particular method due to lack of memory or inability to restore the method’s high-level structure required for optimizing compilation, which may be caused by bytecode obfuscation. To cope with it, the main compiler invokes the so called baseline compiler for such methods. The baseline compiler implements only a few simple optimizations, and thus is able to compile any verifiable bytecode.

If the baseline compiler was invoked at least once during compilation of your project, the main compiler issues a message about the number of methods processed by the baseline compiler. Additionally, it logs the information about the methods compiled with a lower optimization level. The log file, having the executable’s name and the ".vaz" extension, is created in the current directory.

If baseline compilation occurs during compilation of your project, we would appreciate if you e-mail us the resulting ".vaz" log file along with the .class files listed in it. Doing that, you help us improve the quality of our product.

Super Prev Next

xjava launcher

xjava is a command-line tool with the syntax and semantics very similar to those of the conventional java launcher included with OpenJDK. xjava allows you to run your application under the JET Runtime without pre-compilation, that is, using only the JIT compiler (see chapter Mixed Compilation Model).

In the context of Excelsior JET, whose distinctive feature is AOT compilation, xjava is just an auxiliary tool that can be used on the developer’s system for profiling Java applications before optimization. In particular, both Global Optimizer and Startup Optimizer benefit from profile-guided optimizations so xjava is seamlessly integrated with the JET Control Panel.

You may need to invoke it explicitly if you wish to automate application profiling before optimization in the night builds. This section describes how to use the xjava utility.

Super Prev Next


    xjava [ options ]  main-class arguments
    xjava [ options ] -jar jar-file arguments


Command-line options of the launcher.

Name of the main class

Name of the jar file to be invoked.

Arguments passed to the main() method, if any.

Super Prev Next


For compatibility, the xjava launcher supports many standard options of the OpenJDK Java launcher.

-classpath | -cp classpath

classpath is a list of directories, jars and ZIP archives to be searched for class files and resources, separated by semicolons (“;”). Overrides the CLASSPATH environment variable. If that variable is not set and the -classpath / -cp option is not used, the current directory (.) is assumed to be the only entry of the user class path.

Set value of the given system property.

Enable assertions. Assertions are disabled by default.

If package is specified, assertions are enabled in that package and all its subpackages. If only “...” is specified, the unnamed package is assumed. If class is specified, assertions are enabled in that class only.


Disable assertions. Assertions are disabled by default.

If package is specified, assertions are disabled in that package and all its subpackages. If only “...” is specified, the unnamed package is assumed. If class is specified, assertions are disabled in that class only.


Enable assertions in all system classes.

Note: This option is recognized but ignored, because xjava uses system classes precompiled by JET Setup. In the current version, assertions in system classes are always disabled.


Disable assertions in all system classes.

Note: This option is recognized but ignored, because xjava uses system classes precompiled by JET Setup. In the current version, assertions in system classes are always disabled.


Print product version to the standard error and exit.

Print product version to the standard error and continue.
-? | -help

Print a brief help message and exit

Print help on non-standard options and exit.

Set maximum Java heap size. Append “K” or “M” to indicate that the value is in kilobytes or megabytes respectively.

Set Java thread stack size.

Verify that all class files obey language constraints. Without this option, all classes are still verified, but less strictly — without the checks that are disabled in the OpenJDK HotSpot VM for non-remote classes by default.

The following options are specific to xjava:


Select a specific JET run-time. Valid values of runtime are classic, desktop, and server. If runtime is not specified, desktop is assumed.

See Runtime Selection for details.

Super Prev Next

Customizing Runtime error messages

A JET Runtime crash, that is, an abnormal termination of application execution may be caused by bugs in the Runtime or in the application itself. The latter typically occurs due to misuses of JNI functions from within native method libraries that come with certain third-party components or APIs. Such errors are hard to diagnose because a poorly coded native method can corrupt application memory structures in any way.

If this happens on the developer system, the Runtime prints some error information followed by the message

Please contact Excelsior Support Dept. at

If, however, the application terminates due to a Runtime crash on end user systems, the tail message will be replaced with

Please contact the vendor of this application

You can customize this message to print, for example, a contact information of your company’s customer service. To do that, set the system property


when compiling or packaging your application (see Setting System Properties). You may use the \n control sequence in the message to display the following text on a new line.