Knowledge Base

Notice Information in this article applies to Excelsior JET version 3.7 and below.


This article applies to Excelsior JET versions 3.7 and earlier only. Since version 4.0, our product does not incorporate the JetPerfect feature and so it does not support creation of stand-alone DLLs.


The document contains step-by-step instructions on the use of Excelsior JET v3.7 for the creation of a standalone Java DLL and on calling that DLL from a C program. On the first few steps, a DLL dynamically linked with the JET runtime is created. The remaining steps show how to convert it to a standalone DLL.

Source files and build/run scripts for this article may be found in the Supplemental Downloads section.


By default, JET links application code with the runtime dynamically, i.e. your classes are compiled and put into an executable (EXE or DLL) that requires one or more JET runtime DLLs containing precompiled Java 2 platform classes.

A standalone executable may be created with the help of Excelsior JET, Professional Edition feature — JetPerfect Global Optimizer. With JetPerfect, both application classes and required platform classes are compiled in one session. They are globally optimized and statically linked into a single executable (EXE or DLL) that does not need JET runtime DLLs and does not contain redundant code and data.

The use of JetPerfect gives you several important advantages:

  • global optimizations improve code performance
  • smart linking reduces executable size and memory requirements
  • single component linking makes your DLL require no JET runtime DLLs


Let’s consider the sample accompanying this article. First, you have to build a DLL in the default mode.

  1. Compile with javac to produce dllClass.class file:


  2. Build the DLL project in the default mode:

        jc =p =a dllClass.prj

    or open dllClass.prj in the JET Control Panel and build it.

  3. Compile the C test that accesses the DLL.

    The source file main.c contains code that invokes dllClass methods using the standard Java Native Interface and Invocation API (

    Compile and link main.c with the xjvm.lib library that is part of your Excelsior JET installation:

        cl -I%JDKDIR%\include\ -I%JDKDIR%\include\win32\ main.c

    (it is assumed that environment variables JDKDIR and JETDIR contain full paths to JDK and JET directories respectively.)

  4. You can run the test executable:


  5. In order to continue, you need to download and install the JetPerfect add-on, which is available at
  6. Now, to enable global optimizations, a usage list for the DLL must be collected, which includes methods that are called and fields that are accessed at run time via the Reflection API. This cannot be done by analysing your program statically, but the JET runtime can help you build the usage list if you run your application as follows:

    Set the jet.usage.list and jet.default.classloader properties using the JETVMPROP environment variable and run the test application again to create the usage list:

        SET JETVMPROP=-Djet.usage.list -Djet.default.classloader:application

    As a result, the usage list will be automatically collected during execution and will be saved in a file with the application name and “.usg” extension. This example is very simple, but in complicated cases you may re-run your application as many times as you wish, supplying, for instance, different input data. The previously created .usg file will not be overwritten, but newly detected classes, methods and fields accessed via reflection will be added to it.

  7. Re-build the DLL with the option PERFECT enabled:

        jc =p =a dllClass.prj -perfect+

    It will take several minutes, because the required Java 2 platform classes will be compiled together with DLL classes.

  8. Now dllClass.dll contains all the code required for dllClass methods to work, including the Invocation API. So you should change the C program to retrieve the Invocation API routines from that DLL using the GetProcAdr() Windows API call. In the sample program, the change is accomplished through conditional compilation in main.c source: defining ’DynamicUseDLL’ causes loading of Invocation API routines from dllClass.dll instead of xjvm.lib library.)

        cl -I%jdkdir%\include\ -I%jdkdir%\include\win32\
          -DDynamicUseDLL main.c
  9. You can now run main.exe:     main.exe


  1. JetPerfect Global Optimizer:
  2. Excelsior JET 3.7 User’s Guide, Chapter “JetPerfect Global Optimizer”


Article ID: 1
Last Revised On: 15-Sep-2005