Excelsior JET 4.8 US-DST Changes Hotfix is available for download. It is a highly recommended update for JET customers that distribute their software in North America.
Daylight Savings Time (DST) rules used in Excelsior JET Runtime need to be changed accordingly to the US-DST changes for 2007 impacting North American residents and customers. To make changes in JET Runtime you need to install Excelsior JET hotfix (requires Maintenance Pack 2).
Click here for details
Some time ago, I have received an interesting question from one of the readers of my article “Convert Java to EXE: Why, When, When Not and How“. I have the author’s permission to publish my answer and subsequent discussion in this blog. Enjoy.
Frank: I’ve read your article, and I wonder why can’t we just save the executable from the JVM to an exe file, isn’t it naturally being done by the JVM every time it runs a java program ? The bytecode goes through the JVM and becomes executable, so if the people who have access to the JVM can add an extra function to it, instead of running the java program, just write the output to an exe file. Can this be done ?
Such as : Java -exe My_Program.class “My_Program.exe”
Dmitry: It cannot be done in the general case for several reasons. First, a “traditional” JVM such as Sun HotSpot does not compile all classes to native code, but only the “hot” methods of the classes that actually get loaded at run time. Then, you cannot say for a given class whether it will or will not be loaded dynamically, via Class.forName() or JNI, so even if you force the JVM to compile all methods of all classes it loads, some classes will not be loaded on any given test run. For instance, if you precompile an SWT program on a system with a wheel-less mouse, it will fail on a system with a clickwheel mouse due to a missing class.
But most importantly, you may not precompile a class loaded by a custom classloader, because it is not fully defined until it is actually loaded at run time.
That said, we have a special mode in our Excelsior JET product that does more or less what you are writing about even if custom classloaders are used. The limitation is that you still have to deploy all the class files of your application, not only those that were not compiled, as they are required for consistency checks at run time.
Frank: Thanks for your answer. I wonder if there is a way to capture the last snapshot of the memory just before the java program is ready to run, so that all the classes are loaded, or if some classes are still missing when the program begins to run, then write a program that keeps track of all the needed classes during the whole run and save all of them to an exe file, so nothing is missed, it’s like looking at the life time of a program and say, here are all the necessary classes it requires to run, and I’m saving it to the final exe file.
Dmitry: Yes it is possible to do something like this, but with certain limitations. Actually, the JIT Caching mode in Excelsior JET is similar to what you are describing.
One problem with this approach is that a JVM loads and initializes classes on-demand. Even an explicitly imported class only gets loaded when it is first instantiated or when its static method/field is first called/accessed. So when the program is ready to run, only a minor part of all its classes is loaded. Just run a Swing app using “Java -verbose” and you will see that most classes load after the main() method has received control.
Even the standard Java API implementation relies on lazy class initialization, so this behavior may not be changed.
Also, “nothing is missing” is impossible to achieve on virtually any program more complicated than “Hello, World!”. You may traverse the explicit import dependencies, but you may not detect all the classes that may be loaded using reflection or JNI. Consider the following simple example:
---- A.java:
import java.lang.reflect.*;
public class A {
public static void main (String[] args) {
Class c;
Method m;
try {
c = Class.forName(args[0]);
m = c.getMethod(
"main",
new Class[] { String[].class } );
m.invoke (null, new Object[] { args } );
} catch (Throwable e) {
System.out.println(e);
}
}
}
---- B.java:
public class B {
public static void main (String[] args) {
System.out.println("B.main()");
}
}
Note that the class A does not import class B, but if you compile both classes and run the command “java A B”, the program will print “B.main()”. There is no way you can tell that A may load B at compile time.
Even if you have stress tested your program and a certain class was not loaded, you cannot be 100% sure it won’t be loaded when your program runs on a different system with different input data, not to mention that you do not know which classloader would be used to load that class.
To summarize, the dynamic nature and overall complexity of the Java technology make the task of static compilation of Java applications to native code more complicated than one might think. We have spent dozen of person-years developing Excelsior JET and bringing it in full compliance with the Java specification.
Frank: Thanks for the detailed reply. I wonder if you know of any Java launchers or wrappers that doesn’t expose my jar file, which runs my program directly from the exe file it generates without first extract the jar files into a directory ? In other words I want to find the best way to protect the class files from decompilation. How to do that ?
Dmitry: You may wish to check the tools listed in the resource box of the respective section of my article. I think most wrappers and launchers would expose your jar files, but it is possible to hide them using a custom classloader, so some commercial tools could provide such functionality. I know the game Tribal Trouble has its class files hidden this way.
However, it is easy to intercept the classes as they are loaded into the JVM even if they were encrypted.
That said, I am 100% sure native compilation is the best way to protect your Java code if you have to ship it to your end users, as opposed to running it on your own server. The only limitation is that you may not protect classes loaded by custom classloaders, but many desktop apps do not use custom classloaders, and Excelsior JET would let you pack jars with such classes into the executable, much like resources are bound to native Windows apps. To maximize protection, you may also run your app through a name obfuscator before native compilation, but you have to be careful.
For more information, please refer to our Knowledge Base article on this topic:
HOWTO: Maximize protection of your application against reverse engineering
If you also want to copy protect your software, please note that some tools may not correctly handle the executables produced by Excelsior JET due to presence of custom sections. We know that a number of our customers successfully use a tool called PC Guard, you just have to switch off the “Hide executable object names” within the “General” protection options. Also make sure to read this thread in the Excelsior JET forum.