Free tools Windows power users keep installed
One-click scans. No signup required.
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.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problems- Prepare initialization settings. The 1998 code obtains default settings with
JNI_GetDefaultJavaVMInitArgs, using the JDK 1.1-eraJDK1_1InitArgsstructure, and sets the class path so the VM can find the application classes. - Create the VM. It calls
JNI_CreateJavaVM, receiving handles needed to interact with Java. Current Oracle JNI likewise providesJNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args), but current initialization usesJavaVMInitArgsand option strings rather than the 1.1-era structure. - Find and invoke the Java entry point. The wrapper locates class
zipwithFindClass, finds its staticmain(String[])method, constructs a Java string array from the command-line arguments, and calls the method withCallStaticVoidMethod. - Shut down the VM. After Java returns, the wrapper calls
DestroyJavaVMto 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.
Rank #2
| 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.
| 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.
Rank #4
- 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.
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.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Quick Recap
Best Value
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.

