The Win32-Java hybrid

news
Jul 1, 19997 mins

Worried that your Java apps won't run on Windows? Here's a strategy that blends the best of Java with Win32 to create applications that run on Microsoft OSs

While you’re waiting for Microsoft to reveal its future strategy for Java on various Windows platforms (if there is one), you can take advantage of a Windows application development solution that blends Win32 and Java technologies into a single, cohesive unit. This Win32-Java hybrid (WJH) solution makes it possible to quickly create interesting and robust Windows applications, such as a smart card-based security system.

Win32 is Microsoft’s architecture for its 32-bit operating systems. Win32 includes a collection of APIs (application programming interfaces) that Windows applications can call during their execution lifetimes. These applications are written in languages such as C, C++, or Visual Basic, and then compiled into executable code which is stored in DLL or EXE files.

The structure of a WJH application is illustrated in Figure 1.

Figure 1. WJH application structure

The red arrows indicate the composition of a WJH application — a Win32 executable and at least one Java class file. The Win32 executable, among other things, loads the Java virtual machine (JVM) DLL and creates an instance of the virtual machine. The starting Java class file and its main method are identified. This information and its associated command-line arguments are passed to the JVM. The JVM then loads this class file and interprets the instructions located in the file. To assist it in carrying out these instructions, the JVM may call Win32 API functionality or JVM Win32 DLLs that support the JVM.

The idea behind the WJH is to write a small amount of code in C or C++ (the Win32 JVM launcher) and to write most of the code (the application portion) in Java. So what is to be gained by using the WJH approach over the more conventional Win32, C/C++, or Visual Basic approaches? Table 1 lists some advantages.

Table 1. Advantages of the WJH approach
The WJH advantage Description
Simplicity The Java language avoids the more complex language features that are found in C++. These features include multiple inheritance, destructors, and operator overloading (Java offers a feature known as an interface to offset its lack of multiple inheritance). Java’s simplicity results in a shorter learning curve.
Reliability The Java language does not support the concept of pointers. The misuse of this language feature often results in program crashes or malicious behavior. Java was designed to be reliable and secure.
Wide variety of free APIs Sun has released a wide variety of free APIs for Java. These APIs are designed to offer current Win32, Unix, and other OS functionality from a portable point of view.

For all its advantages, Java has one significant disadvantage — performance. Virtual machines slow performance. However, the advent of the just-in-time compiler (that part of the JVM which compiles Java instructions — known as bytecode — into native machine instructions during execution) is fast causing the performance issue to disappear.

So, how do we create a WJH application? The best way to answer that question is to study an example. To that end, I’m presenting a text editor application that is partly written in C (I didn’t need C++ for this application) and mostly written in Java.

The text editor application is called te. The Java section of the program was built using JDK 1.2. The C portion was built using Borland C++ 4.52. (Yes, you can write meaningful WJH applications using a non-Visual C++ development tool.)

Table 2 identifies the source and executable files that constitute the Java section of the program. These files are distributed in an archive called te-java.zip. To download these sample code files, click here.

Table 2. Java files
File Name Description
te.class Executable file
te.java Source file

Table 3 identifies the source and executable files that constitute the C portion of the WJH. These files are distributed in an archive called te-c.zip. To download these sample code files, click here.

Table 3. C files
File Name Description
jni.h JNI header file (comes with JDK)
jni_md.h JNI header file (comes with JDK) — slightly modified for use with Borland C++
te.c Source file
te.exe Executable file
te.ide Project file

If you want to learn how te works, first study te.c (the source for te.exe) and then te.java (the source for te.class).

For the purposes of this article, it isn’t necessary to go through all of te.c, since it contains a generous helping of comments. However, there are a few observations worth noting.

As you probably know, there are two kinds of Windows applications: console-based and GUI (graphical user interface)-based. This example utilizes a console-based format for te.exe; however, it doesn’t matter whether or not you choose console or GUI as your compiler option when creating WJH applications, because the Win32 part of the app wouldn’t normally register window classes, create windows, or contain messaging loops.

In the example, we disabled Ctrl-Break key presses so that they won’t disrupt te. You can do this by calling the Win32 SetConsoleCtrlHandler API. Without this call, the JVM could abort while executing Java instructions and remaining code in the Win32 executable wouldn’t be reached. Do you have to disable Ctrl-Breaks? That depends upon your application, but it’s always better to play it safe.

The LoadJVM function (in te.c) queries the Windows registry for the location and name of the JVM DLL. This information is located in a subkey of the HKEY_LOCAL_MACHINE root key. This subkey is SOFTWAREJavaSoftJava Runtime Environment1.2 and contains a RuntimeLib entry. The value associated with this entry is the location and name of the JVM DLL.

Finally, let’s examine te.java. Figure 2 shows te‘s main window.

This window consists of a single File menu (with Load, Save, and Quit options), a text area for viewing and editing the contents of a file, and a pair of status lines (one line identifies currently loaded or saved file while the other line displays error messages).

Before concluding, let’s summarize what you need to do in order to run the text editor on your computer.

  • Install the JRE
  • Place te.exe and te.class in the same directory
  • Set the CLASSPATH environment variable (a Win32 environment variable that the JVM uses to locate class files) to point to the directory containing te.class
Caution
In April 2006, I received a question from a JavaWorld reader who was unable to run te.exe and see the te GUI. I discovered that this problem exists because of a hard-coded registry path in the te.c source code. Back in 1999, when I wrote te.c, J2SE 1.2 was current and I hardcoded its 1.2 version number as part of the following registry path: SOFTWAREJavaSoftJava Runtime Environment1.2. Because subsequent versions of Java place different version numbers below the Java Runtime Environment subkey, this path no longer works. For example, J2SE 1.4 places 1.4 and 1.4.0 entries below Java Runtime Environment. To make a te.exe that works in that environment, you would replace that path’s 1.2 with either 1.4 or 1.4.0, as shown in the following code fragment (from te.c‘s LoadJVM() function), and recompile:
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                  "SOFTWAREJavaSoftJava Runtime Environment1.4",
                  0,
                  KEY_ALL_ACCESS,
                  &key) != ERROR_SUCCESS)
In hindsight, I should have come up with a better way of making te.exe portable to various versions of Java.

While the Win32-Java hybrid approach won’t be useful in all situations, it’s a good little hack to keep your Java skills relevant and your Java code running in a Windows environment. With a little practice, this alternative method can become a valuable tactic for getting through the turbulence that now has the Java community rattled with uncertainty.

Jeff Friesen, a computer consultant and software developer, works with a wide variety of software technologies, including C++, digital signatures/encryption, Java, smart cards, and Win32. He also writes Java articles for JavaWorld and C++ articles for PC Magazine.