JET (Just Enough Time) static AOT (Ahead Of Time) compliler.
What Is JET?
- JET
is a static compiler that lets a developer create standard exe file applications that
load and run very quickly.
- With JET you can say simply someprog.exe instead of the usual
more verbose java.exe -jar someprog.jar on the command
line.
- JET
applications will run even if the Java JRE (Java Runtime Environment) is not installed.
- Ordinary jar files are very easy to reverse engineer. JET
executables are almost impossible to reverse engineer. If you are a developer this makes it difficult for
pirates to defang your licencing restrictions or to pirate your code.
- With the use of JetPackII, JET-compiled, programs are self-installing just like Windows apps written in
C++.
- JET-compiled programs look like perfectly ordinary familiar Windows exe files.
- There is no royalty for JET-compiled applications.
- The catch is, unlike the conventional jar version of the application, they are no longer
WORA (Write Once, Run Anywhere). You can only use the Windows version of
the JET-compiled application on Windows and the Linux version on Linux, nowhere else.
Unless you have Windows or Linux you must use the conventional jar version, e.g. if you have a Mac.
- JET
applications require 32 MB run-time library which is usually included and
downloaded with every application and update. It contains only the parts of the run time actually used. Pretty
must the smallest distributable is 32 MB, for even the simplest utility and the
smallest exe file is about 8 MB.
JET is
Excelsior’s Java optimiser and native code generator, created in Novosibirsk Russia. There are currently
versions for Windows and Linux in English. Excelsior is not responsible for the accuracy of anything said on this
page. It is based on my personal experience with JET over a number of years.
JET Version 8.0 supports up to Java 1.6.0_43.
(The most recent Oracle release is 1.7.0_25 ), currently one full version behind.
You can use the 1.7.0_25 compiler, but you must use -target 1.6. Even if you avoid the new 7.0 features
JET cannot handle code compiled with -target 1.7.
Last revised/verified: 2013-04-19. JET
supports XP/W2003/Vista/W2008/W7-32/W7-64/Linux
JET comes with a precompiled JRE, so you don’t actually need to install a
Oracle JRE 1.6.0_43 though obviously you will need
some JDK (Java Development Kit) for development, usually JDK 1.7.0_25.
JET 8.0 now lets you natively compile Tomcat and Tomcat applications.
Support for JDK 1.7.0_25 has been delayed to expedite release of 64-bit JET.
There are currently no MPs (Modifier Packs) to download and install for Jet 8.0.
Why Use JET?
Downside of JET
- JET
executables are considerably larger than the equivalent jar. They contain much of the JRE in compiled form.
In contrast, distributed jars do not contain any run time. However, the RAM overhead of Excelsior
JET
Runtime is smaller than for the JRE. The distributed bundle produced by Excelsior JET
may be substantially smaller than the JRE alone, and the installed application will occupy less disk space
than the JRE. So if you are bundling the JRE with your app now, your JET
distributables will be
smaller; if not, they will be larger. This true for small apps even if you don’t use the Java Run-Time
Slim-Down feature.
The files I send people are a minimum of 4 MB, rather than the tiny jars I would send otherwise. (My apps
tend to be quite small, usually under 100K jars). I have to post the
distributables on my website for pickup rather than sending by email. You could also send these via WinZip Courier.
- JET
is usually a month or two behind Sun in supporting new JVMs. Currently it is 5 versions behind the
1.7.0_25
where the current Sun JDK is 1.7.0_25. Last revised/verified: 2008-02-18
You can still compile with the current version of javac.exe and debug with the current
version of java.exe.
- The runtime must exactly match the code. You can’t run new code on old runtimes or vice versa. This
means when a new version comes out, you will likely at some point recompile and redeploy the entire universe of
every JET program you ever wrote on every customer machine. In development, an executable
finds the runtime by scanning the path. If you uninstall a version of JET
or replace it with a newer version, all code compiled with it will stop working since it can’t find the
old runtime. You must recompile it with jc.exe.
- The scheme for distributing the support DLLs, and compiled JREs seemed brittle, at least in the early
versions. I have not done any further distribution experiments since about 2003.
JET
has improved drastically in other areas since then. JET worked beautifully on my own machine, but sometimes
mysteriously stopped working on other machines, or never worked, when I deployed. I got error messages saying
that DLLs had gone missing or that the JET runtime had not been installed. It is hard to remotely
troubleshoot such problems with an unsophisticated customer. Until I redo my experiments, and can vouch all is
now well, I suggest you experiment with the evaluation version to make sure distribution and remote installs
work smoothly for you. They are probably OK now.
- It installs the JET runtime in theAppdir/JET
RT so that if some other developer is using JET, or you are providing several applications, there will be
duplicate copies of the JET
runtime. With today’s terabyte disks this is not longer so much of a concern.
When Not To Use JET
- JET
is not a replacement for Sun’s javac.exe. You use JET
to compile the jars that javac.exe and jar.exe produce. You
still use Sun’s javac.exe to do the source code compiling and for
debugging.
- JET
does not have debug features comparable to the trace in Intellij Idea. You do your debugging on the class files
before using JET.
- JET
compiles take considerably longer than a javac.exe compile. You don’t use
JET
until you are fairly sure the code is debugged.
- The only platforms Excelsior JET supports at the moment are Windows and Linux. If you are considering compiling
your Java applications to native code to prevent reverse engineering, but some of your customers use Macs,
Excelsior JET 6.0 won’t help you. If you are using JET
for the speed, you could ship natively compiled JET versions of your app to Windows and Linux users and the
bytecode class files to all others.
Example of Command Line JET Use
You can define a JET project and compile it, complete with installer using a GUI. It is a multi-step
process, but not complicated. You can also compile in various ways from the command line or *.bat scripts.
Example of ANT JET Use
My projects are typically quite simple, and I compile them with ANT scripts simply by handing a jar to the
JET
compiler.
Detecting JET
Your program can detect that is in running under JET by looking at the system properties such as:
java.vendor=Excelsior, LLC
java.vm.name=Excelsior JET
java.vm.vendor=Excelsior, LLC
java.vm.version=1.6.0_31
e.g.
This may be important since JET does not support Throwable. getStackTrace() by default. You must request stack trace support, which slows the programs down.
Kudos
I have been very impressed with the JET people. Even without an official support contract, the
JET people
have responded quickly and thoroughly to my bug reports and suggestions for improvements. They have provided
better service free than most companies provide for hefty fees. I wonder what they do for an encore when you do
sign up for support! Optimising compilers are notoriously buggy, yet JET
seems to generate flawless code time after time. I have never encountered any wrong code generated.
The only serious problem I have is Jet does not have as many built-in
root SSL certificates as Oracle Java 7. This means my apps
when running under Jet have trouble screen scraping some https: websites. You can of course
copy Oracle’s cacerts file on top of Jet’s for your
own personal use in testing and debugging, but you cannot legally do that for programs you distribute.
Purchasing JET
How Does It Work
See Excelsior’s simplified overview of how JET works.
How does JET work? It needs somebody else’s compiler such as Sun’s to produce the
byte codes, then it converts class files to a native Windows EXE file. Why is it so fast? It is able to determine
if methods overriding a particular non-final method are never actually called in a particular application and
therefore inline the method or generate direct calls of it. JET
will allocate some local objects on the stack. It can eliminate a remarkable amount of code that is not
necessary, e.g. redundant checks for null by both caller and callee. JET
does loop versioning, i.e. it
creates a special safe version of loop code used when it knows that various exceptions can’t possibly
happen, e.g. subscripts out of range. This way it can avoid much of the overhead of the Java safety net.
There are now three versions (four if you
count the Embedded edition) described in their FAQ. It supports all of Java including class.forName dynamic class loading.
Preparing An Application for Distribution
Here is an overview of the process of preparing Jet-compiled
application for distribution. I am describing the process for Windows, but it is similar for Linux.
Let us assume your application is called
Rabbit and will eventually run on the client
machine as rabbit.exe.
- Write and debug your Rabbit.java
java source code in an IDE such an IntelliJ
Idea.
- Compile your Rabbit.java
source with javac.exe, probably using Ant or Maven.
- Bundle your Rabbit.class files into rabbit.jar with jar.exe or
genjar.jar.
- Compile (i.e. convert class files in the jar into native machine code)
your rabbit.jar from the command line with jc.exe or for finer control use the Jet Control Panel GUI to produce a rabbit.exe file. The compiliation tweaking hints are stored in
the human-readable rabbit.prj file. The rabbit.exe file will run locally. It is quite small
since it uses the pre-installed Jet Run time and library of precompiled
JDKs. It leaves behind intermediate files in jetpdb to speed up future compiles.
rabbit.xbind.script contains a list of DLLs (Dynamic Link Libraries) that rabbit needs to run.
With the Jet Control Panel you can implement
a splash screen that comes up immediately without having to write any code.
- Use the JetPack GUI to bundle up your
executable, jet compiled parts of the JDK that it uses and library code into
one big setup-rabbit.exe self installing exe bundle. That is what you distribute. JetPack stores its
tweaking hints in the rabbit.jpn file.
- You then post the fat setup-rabbit.exe on a website or burn it on a CD and distribute
it to your client.
- When the user runs setup-rabbit.exe it
unpacks itself and places its various pieces, including rabbit.exe, and runtime
on the hard disk, then sets up desktop icons
and menus.
64-Bit
JET is
32-bit with 64-bit planned for 2009. When the JET-compiled 32-bit executables run on 64-bit windows you have a 3 GB address space. Sun HotSpot requires a contiguous address space
for the heap, whereas Excelsior JET (and, for that matter, JRockit) does not. So if you have lots of RAM, but the
virtual address space is fragmented due to DLLs already loaded, Excelsior JET
may be able to allocate more objects on the heap than HotSpot. Further, with JET
you don’t have to specify
the heap size. You can have it automatically adjust as it runs taking more or less memory depending on how much
is available in the system. This lets you automatically exploit the whole machine when there are no other jobs
running.
Have a look at the Which utility for code to recognise
JET
executables and whether they are up-to-date, compiled for the latest runtime.
Components
| JET Components |
| File |
Purpose |
| *.prj |
Human-readable project file. |
| jc.exe |
Compiler. Converts *.jar to *.exe or *.class to *.exe. |
| JETPackII.exe |
prepares self-installing apps. |
| JETSetup.exe |
Adds support for yet another JVM (Java Virtual Machine). |
| LaunchPad.exe |
Project control, GUI control of the compiler. |
Viewing Generated Assembler
JET
versions prior to 5.0 allow you to view the assembler generated by using the -genasm+
key (aka compiler option switch) in the project file to generate assembler instead of object files. This was an
undocumented feature. For JET 5.0+, you will need to use a conventional disassembler to view the generated code. JET
-generated code is unusually difficult to reverse engineer since the compiler does loop versioning and hiking,
and is so creative at devising code that does the same thing as the original but in a quite different way.
Maintenance Packs
From time to time, Excelsior issues MP (Maintenance Pack)s to upgrade the Jet compiler, runtime, and highest level
of the Oracle Java runtime supported. When you install these, for all practical purposes all your Jet application
exes will stop working until you rebuild them. It is possible to ask Jet to retain obsolete runtimes or to
regenerate them. However, I have never been able to get old apps to work without rebuilding them. I have problems
with incompatibility between versions of Java, versions of Jet, and something called binary compatibility level
which might be sort of build number. If I fully understood how this worked under the hood, presumably, I could
manage a corral of both obsolete and up-to-date Jet software and my Jet-compiled applications of various
vintages.
I impatiently cut the Gordian knot. I just delete all my old exes, and rebuild everything. The catch is my
build process uses custom Jet-compiled applications. I can't rebuild because all my tools stop working. I
kludge my way through this chicken-egg problem mainly by reverting to executing the orginal jars instead of the
Jet-prepared exes. I can ease the pain of the transition by first temporarily rebuilding my exes without first
rebuilding my Java source or jars, then rebuild the java and Jars (using recently-rebuilt Jet-complied build
tools) and then rebuild all the Jet exes a second time.
If the setup utility stops working after installing a maintenance pack, just reboot. It might be a
good idea to reboot after the install on general principles.
I wrote a free utility called Which to, among other things, help you
find obsolete Jet-compiled application exes.
JETPack Installer
JETPack bundles up self-installing applications. It is much like an InstallAnywhere for Java/
JET. It
allows:
- Automatically bundle the required Excelsior JET Runtime files.
- Set up shortcuts on desktop and menu.
- Assign an optional *.ico icon and *.bmp splash screen for
your app (done in the JET project, not the JETPack installer). You don’t need to write any code to
get this feature built into your executable.
- Display a splash screen during install.
- display a EULA
- Versions 3.7 and earlier required you to have Sun’s JRE installed as well a
JET DLL
runtime library on machines running the JET executables. Starting with version 4.0, there is no longer any need to have the corresponding JRE installed, just the runtime.
Unfortunately, an option to create fully self contained executables that could run without the DLLs has gone.
JETPack will bundle the application and the DLL runtime library into a rather bulky download: about 9MB for a
mid-size Swing application such as jEdit.
JETPack is very easy to use. Just fill in the blanks.
JETPerfect
JETPerfect was the global optimiser that came with the Professional Edition. It is no longer supported. It did a
very time consuming and labour-intensive form of global optimisation creating a stand-alone executable.
Auxiliary Files
When you first install JET for development, if you don’t accept the default JVM, it has to compile the
entire JVM set of class files. This takes about an hour on modern machines or over twelve hours on clunkers with
less than 512 MB of RAM. People who just want to run JET-compiled apps don’t have to do this.
Obviously, to use JET, you need the JDK installed on each
developer machine. To run the programs you need the JET DLL runtime and the application. The DLL contains a compiled
version of the JRE. Even though Sun’s license prohibits partial JRE redistribution, Excelsior has come up
with a solution that enables you
to omit the unused Java SE APIs without breaking the Sun license. In a general case however, the entire Java SE
API has to be bundled with your JET application to deploy it on a customer machine.
JET 7.0 Improvements
- The big improvement is the ability to compile Tomcat and Tomcat applications.
- The 64-bit alpha version is out. The compiler runs 64-bit and the run-time is 64-bit. The optimisations are
not hooked up yet, so this is just for experimenting.
- It also features multi-app executables.. With it, you may compile several
applications into a single executable to simplify deployment and maximize code and data sharing without
manually extracting common parts into dynamic libraries.
- It now supports Windows 7.
- Code runs 1.2 to 3 times faster.
JET 6.5 Improvements
- Better Eclipse integration.
- Faster memory allocation and garbage collection.
- JIT compilation is twice as fast.
JET 6.4 Improvements
- Optional encryption of literals and resources to make reverse engineering or tampering harder.
- Twice as fast startup of the finished applications.
- faster compiling, both AOT
and JIT (Just In Time)
run time addition of dynamic classes).
- slimmer distributables.
- Not-so-dumb compilation: now a settings change that has no impact on generated code results in a re-link
instead of a full build.
JET 6.0 Improvements
- Keeps getting faster
- Support for Java 1.6, e.g. annotations.
- more flexible installer
- Plug-in for IntelliJ Idea
- more efficient memory management and better register allocation.
JET 5.0 Improvements
- JET
creates only one extra directory per project called jetpdb. It used to create a large
directory tree with names duplicating the branches of your packages. This caused havoc with tcc/TakeCommand CDD. The new system has a little
PDB (Project DataBase) for each project for JET’s files.
- Slim-down. The
distributables are slimmer, 8 MB for Swing/AWT and as small as 5 MB for SWT or LWJGL. You can distribute a
package that consists of your app, and just the parts of the JRE that it uses. This prunes down the size of the
distributable.
- Start up time 30% faster when compiled with the global optimiser.
- 1.7 times faster execution on some benchmarks because of: new loop
optimizations, faster floating-point operations, faster memory allocation and more effective implementation of
other runtime routines.
- Faster compilation.
- IntelliJ Plugin.
Tips
- To suppress the voluminous progress messages, use jc -DECOR= on the command
line.
- JET
finds its files using a registry entry at:
HKEY_LOCAL_MACHINE\SOFTWARE\Excelsior\Excelsior JET\6.0 pro
InstallPath=F:\Program Files\jet6.0-pro.
JET Glossary
- Adaptive Heap Size
- distributable
- A program bundle distributed to customers. When it runs, it installs the program on the clien’ts
disk. It contains the program, auxiliary DLLs, data files, icons etc.
- Excelsior
- The company headquartered in Novosibirsk Russia that makes JET.
- executable
- program containing machine language code that can run on Windows or Linux. The JET
native compiler produces executables. You can run these directly on the machine used to compile them. You must
bundle them first into distributables if you want to run them on other machines.
- jc.exe
- JET
native compiler than converts class files produced by javac.exe to Windows or Linux
native executables (*.exe files). You control whether to use production or beta jc.exe
by putting the corresponding directory on the path.
- JET
- A native Java compiler for Windows and Linux from Excelsior than includes an installer. It comes is three
versions, standard, professional and enterprise.
- JET Enterprise
- the high end version of the JET Java
native compiler. The main advantage over the professional version is the optimised server runtime for extra
speed.
- JET Standard
- the entry level version of the JET Java
native compiler.
- JET Professional
- the intermediate level version of the
JET
Java native compiler. The main advantage over the standard version is slimmer distributables. This is what I
use.
- JETPackII
- The GUI used to bundle a JET application up for distribution.
- JRE
- JRE.
Sun’s Java run time. It is not required on either the development or client machine to run
JET-compiled applications. A JET
-compiled version of it is automatically bundled with distributed application along with Excelsior-written
native classes and DLLs.
- JET launchpad
- the GUI used to set up JET projects to control how they are compiled.
- JDK
- JDK.
Sun’s Java development tool. It is not required on either client machine to run
JET-compiled applications, though you would normally have a copy of the JDK on the
development machine.
- versioning
- a powerful optimisation technique JET uses to create several specialised versions of a loop body
so that it does not have to check conditions in the middle of the loop body. It selects the loop body version
at the top of the loop. This removes time-consuming loop body jumps and improves code locality, and avoids
instruction pre-fetch cache flushing. The technique is almost impossible to do by hand in assembler. This is
one of the many reasons JET can often out-perform the best assembler hand coding.