Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To run Java code from a native Windows program, a C++ executable can embed the Java virtual machine (JVM) through JNI’s Invocation API, call a Java class’s main method, and then shut the VM down. Jeff Friesen’s 1998 tutorial, “Merging Java and Win32,” demonstrates the approach with a small ZIP utility. Its JDK 1.1.5 and Visual C++ 5.0 instructions are historical; the underlying embedding concept remains part of Oracle’s current JNI specification.

What “merging Java and Win32” means

The design splits responsibility across two parts. A native C++ executable handles Windows process startup and command-line arguments; Java performs the application work. The C++ side is a thin launcher rather than a replacement for the Java program.

The boundary between them is JNI, the Java Native Interface. Its Invocation API allows a native application to create and control a JVM. Oracle’s current specification describes JNI_CreateJavaVM as loading and initializing a VM, attaching the calling thread as its main thread, and returning JNI interface access. Oracle’s Java SE 27 Invocation API specification also states: “Creation of multiple VMs in a single process is not supported.”

How the native launcher starts Java

Friesen’s 1998 example follows this lifecycle: prepare VM options, create the VM, locate the Java class and entry point, pass arguments, invoke Java, and destroy the VM. The historical API names and initialization structures differ from current JNI examples, but the overall handoff remains recognizable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Prepare initialization settings. The 1998 code obtains default settings with JNI_GetDefaultJavaVMInitArgs, using the JDK 1.1-era JDK1_1InitArgs structure, and sets the class path so the VM can find the application classes.
  2. Create the VM. It calls JNI_CreateJavaVM, receiving handles needed to interact with Java. Current Oracle JNI likewise provides JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args), but current initialization uses JavaVMInitArgs and option strings rather than the 1.1-era structure.
  3. Find and invoke the Java entry point. The wrapper locates class zip with FindClass, finds its static main(String[]) method, constructs a Java string array from the command-line arguments, and calls the method with CallStaticVoidMethod.
  4. Shut down the VM. After Java returns, the wrapper calls DestroyJavaVM to end the embedded VM.

This is an in-process arrangement: the Java program runs inside the native executable’s process, not as a separately launched Java command. A process should not try to create a second JVM in the same process; Oracle explicitly says multiple VMs in one process are unsupported.

The worked example: a Java ZIP utility

The Java class in the tutorial uses java.util.zip.ZipFile to read an archive. It supports two modes, and the C++ launcher passes the user’s arguments through to the Java main method.

Command form What the example does
zip archive Lists the names of entries in the archive.
zip -x file archive Extracts the matching file from the archive.

The example illustrates the architectural point: argument parsing and the Windows executable shell can stay native, while the archive logic is implemented in Java. It is a console-oriented demonstration, not a complete native Windows GUI application.

What the historical build requires

The instructions target JDK 1.1.5 and Microsoft Visual C++ 5.0, so their paths, libraries, and runtime filenames should be read as period-specific build details—not as current installation advice. The native project includes the JDK headers from the main include directory and includewin32, then links javai.lib.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Historical file or setting Role in the tutorial
zip.exe Native C++ launcher for the application.
zip.class Compiled Java ZIP utility class.
classes.zip JDK class archive used by the 1.1-era runtime setup.
javai.dll JVM runtime DLL used by the launcher.
javai.lib Import library linked by the Visual C++ project.
zip.ini Configuration file that stores the Java installation path.

Friesen noted a distribution cost of “eight megabytes a pop” if each copy included a separate classes.zip. That is a figure from the 1998 article, not a current Java runtime size.

Console versus GUI, and deployment trade-offs

The ZIP example is console-first. The article says a graphical variant would also need the JVM’s winawt.dll and other support DLLs. That adds runtime dependencies beyond the small launcher and application class, so embedding the VM does not make Java deployment self-contained by itself.

  • Integration: JNI provides a defined C/C++ to Java boundary, but the native wrapper must perform VM setup, class and method lookup, argument conversion, invocation, and shutdown.
  • Runtime footprint: The executable depends on the Java runtime and application classes; GUI applications may need additional AWT components.
  • Language and platform: Java can supply application logic, but using Win32 APIs in the native layer keeps that portion Windows-specific. Java’s portability does not make a Win32-facing launcher portable unchanged.
  • Licensing: Friesen warned that Sun’s license required runtime files to be distributed without modification. That is a historical statement about the license context of the article; it should not be treated as current legal guidance.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

What remains useful—and what does not

The tutorial’s central idea still applies: a native host can embed a JVM and invoke Java code using JNI. The exact 1998 source setup does not transfer directly to present-day Java or Windows toolchains. In particular, its JDK1_1InitArgs, javai.dll, classes.zip, and Visual C++ 5.0 project are historical specifics. Current Oracle documentation is the appropriate reference for the current Invocation API signatures and constraints.

Friesen’s article framed the approach as a way to write Win32 applications in Java instead of C++ and “save yourself some time and effort.” Its ZIP utility demonstrates that division of labor, while also exposing the practical costs: native/JNI glue, JVM lifecycle management, and runtime packaging. The article is Jeff Friesen’s “Merging Java and Win32: A new way to develop Windows applications,” published July 1, 1998.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.