Super Prev Next

JC tutorial

The Excelsior JET command-line compiler comes integrated with the project system as a single utility called jc. This Chapter demonstrates practical use of the command-line compiler from a simple “Hello, world” program to a multicomponent (EXE plus DLL) application.

It is assumed that JET has been properly installed and its default configuration has not been changed.


Super Prev Next

Simple applications

If your Java application consists of a single class file, like the "Hello world!" sample in the samples/Hello subdirectory of your JET installation, simply specify the name of that class file as a parameter to jc:

    jc hello.class

jc shall compile hello.class to native code and automatically invoke the linker that shall create the hello.exe executable.

Similarly, if your application consists of several class files residing in the same directory, pass to jc the name of the class which you specify on your Java launcher command line:

    jc MainClass.class

This would produce an executable file MainClass.exe.

Finally, if all your application’s classes are in a single .jar file, which you run on the JVM as

    java -jar MyApp.jar

you may compile it to MyApp.exe executable as follows:

    jc MyApp.jar

If not already present, subdirectories bod, obj, and sym are created during compilation. They are intended for storage of intermediate files.

The above samples illustrate jc operation in the default mode, called the MAKE mode. In that mode, the compiler recursively processes all classes used by the class specified on the command line. If intermediate files for a particular class do not exist or are out of date, that class is compiled.

If the class specified on the jc command line is a main class (i.e. it has a static void main (String args[]) public method), the linker is invoked automatically after compilation to produce an executable file. Otherwise, the compiler issues an error message.


Super Prev Next

Command line parameters

Along with the name of the .class or .jar file, you may specify various options on the command line. The relative order of command-line parameters is irrelevant.

For instance, if you want to pack resource files (images, audio clips, etc.) from the source jar to the resulting executable, switch the BINDRESOURCES option on:

    jc MyApp.jar +bindresources


Super Prev Next

Project files

In more compicated cases, e.g. if your application classes are distributed among several directories and/or .jar files, are organized into packages, etc., we recommend you to write a project file.

In the simplest case, a project file consists of a single line specifying the name of the main class:

    !module hello.class

but it may also contain various option settings, file lookups, import libraries, etc.

Note: !module and !batch directives (see Project files) have to be specified at the very end of a project file.

Below is a project file containing some option settings. Notice the percent sign indicating comment lines.

    % disable stack allocation
    -genstackalloc

    % bind resource files to the executable
    +bindresources
    
    % reduce stack size
    -stacklimit=100000
    
    % main application class
    !module MainClass.class

    % jar file with resources
    !module Resources.jar

To compile a project, specify its name on the command line and use the =p parameter to force the compiler into the PROJECT mode:

    jc =p hello.prj


Super Prev Next

File lookup and placement

The JET compiler gives you complete control over location of your bytecode files, intermediate files, and resulting executables. Using LOOKUP equations, you specify directories and jars from which jc shall read your class files, as well as directories into which it shall place intermediate files and executables:

    -lookup=*.class=./class;./jars/MyLib.jar
    -lookup=*.obj=./tmp
    -lookup=*.exe=C:\MyJavaApps
    !module MainClass.class

In the above sample, the compiler is told to look for *.class files first in the class subdirectory of the current directory, and then in the archive ./jars/MyLib.jar. Object files are to be placed in ./tmp (overriding the default ./obj), and the resulting executable shall go to C:\MyJavaApps.

A few hints:

  1. If you have multiple projects using a common set of files, you may quickly tune the lookups by employing environment variable substitution:

        -lookup=*.jar=$(MYJARS);

    Now, if you move your jar files to another directory, you just have to change the environment variable MYJARS accordingly.

  2. Using the base directory designator "$!", you can bind lookup paths to the directory in which the project file resides:

        -lookup=*.class=$!/class

    By doing so you ensure that regardless of what the current directory is during compilation, the class files are read from the class subdirectory of the directory containing the project file.


Super Prev Next

Specifying input files

Any file may be specified as an input file to jc, though files of unrecognized types are ignored. The JET project system distinguishes files by their extensions. It passes bytecode (.class) files to the compiler. Files of other types, such as libraries (.lib) or icons (.ico), are passed to the linker.

There are two project file directives that allow you to enumerate the set of jc input files. The !module directive is followed by a file name:

    !module Foo.class
    !module Bar.class
    !module c:\Thirdparty\lib\Comm.jar
    !module icons/MyApp.ico

whereas the batch directive facilitates processing of a group of files of the same type residing in a particular subdirectory of a lookup directory for that file type:

    -lookup = *.class=C:\Work\Lib
       .  .  .
    !batch *.class com/MyCorp/MyPackage

See The !batch directive for more information.


Super Prev Next

Packages

Your application may include classes that are organized into packages. For packages located in .jar or .zip archives, you just have to specify those archive files in LOOKUP statements in your project file:

    -lookup=*.class=c:\Packages\MyPackage.jar

If you have the package as a set of separate .class files, do the following:

  1. In a certain directory D, create a directory structure exactly matching the package structure and appropriately place the .class files. For instance, if your package is named com.MyCorp.MyPkg, create subdirectories com, com/MyCorp, and com/MyCorp/MyPkg and place the package class files into the latter.
  2. Specify the directory D in a LOOKUP statement in your project file. For instance, if you placed the com.MyCorp.MyPkg package class files into C:\Packages\com\MyCorp\MyPkg , add the following line to your project file:

        -lookup=*.class=C:\Packages

Now the compiler is able to find the classes from your package referenced by other classes. If you want your executable (usually a DLL) to include the entire package, use the !batch project file statement in addition to the actions described above:

    +gendll
    -lookup=*.class=C:\Packages
    !batch *.class com/MyCorp/MyPkg


Super Prev Next

Dynamic loading

The compiler is unable to automatically recognize classes that are not imported, but loaded at run-time using Java dynamic loading facilities (Class.forName() and the JNI function FindClass()). Such classes will not be compiled and linked, and ClassNotFoundException will be thrown at run-time on an attempt to load one of them, unless you are taking advantage of the mixed compilation model. If you are not, you have to explicitly specify names of dynamically loaded classes in your project file:

       .  .  .
    !module MainClass.class
    !module DynamicallyLoadedClass1.class
    !module DynamicallyLoadedClass2.class
       .  .  .

Of course, adding classes one by one may be very annoying. Fortunately, JET project system provides mechanisms to specify multiple classes at once:

See also Using multiple components.


Super Prev Next

Dynamic link libraries

With JET, you may create both EXEs and DLLs. This allows you to share common classes and class libraries among multiple applications and employ the Java dynamic loading facility (see Multi-component applications).

The following instructions have to be carefully followed when building DLLs:

  1. Class files for each component (EXE or DLL) have to reside in separate directories and/or jar files and you have to set up file lookups so that class files of a particular component may not be found by the compiler when building another component. Otherwise code and data duplication may occur, resulting in unwanted overheads and most certainly in program misbehavior.
  2. At the same time, symbol (.sym) and optionally precompiled (.bod) files of classes that were compiled and linked into a certain DLL A have to be available to jc during compilation of any classes that import classes from A.

Therefore, to build a DLL, you have to do the following:

  1. enable the GENDLL option in your project file;
  2. set the desired name of the DLL using the OUTPUTNAME equation (if different from the project file name);
  3. place class files that should be compiled into the DLL into a separate directory(ies) or jar(s), and set the lookups accordingly;
  4. create separate directories for symbol and precompiled files and set the lookups accordingly;
  5. specify all classes that you want to be exported from the DLL in the project using !module or !batch directives.

Sample project:

    +gendll
    -outputname=MyLib
    -lookup=*.class=./MyLib
    -lookup=*.jar=./MyLib
    -lookup=*.sym=./MyLibsym
    -lookup=*.bod=./MyLibbod
    !module MyLib.jar
    !module Lib1.class 
    !module Lib2.class

The result of compilation of the above project shall be the file MyLib.dll.

Then, in a project file for an executable that will be using classes from MyLib.dll, do the following:

  1. append directories, in which symbol and precompiled files for MyLib.dll classes reside, to the respective lookups;
  2. specify MyLib.dll as a !module.

    -lookup=*.class=./MyApp
    -lookup=*.sym=./MyAppsym;./MyLibsym
    -lookup=*.bod=./MyAppbod;./MyLibbod
    !module MainClass.class

    !module MyLib.dll

For more information about dynamic linking, please consult Chapter Dynamic linking. See also the programs in samples/DLL.


Super Prev Next

Understanding compiler messages

When the compiler detects an error during compilation, it displays an error message. The compiler may also issue warnings and notices. The default message format includes file name, position inside the original source file /Only for class files that contain line number information./ , message type indicator ([N]otice, [W]arning, [E]rror, or [F]ault), message number, and message text itself.

Assuming that the input class files are correct, jc shall normally report notices and warnings only. An error or fault reported during class file compilation indicates a misconfiguration, such as inability to locate or create a file, or a compiler bug.

For a full description of compiler messages, see Chapter Compiler messages.

Super Prev Next

Example

* [ Dhrystone.java 278.01 W900 ]
*  redundant code eliminated
#        charLoc1 = charPar1Val;