General porting considerations
You will need to consider a number of issues before you port Java™ applications to 64-bit systems.
The Java platform on 64-bit processors
- On 31-bit systems, the maximum Java heap space (where Java objects are held at runtime) is 2GB whereas 64-bit systems can have heap spaces up to (and exceeding) 32GB. This larger heap space is essential for Java applications to be able to use the full capabilities of large, powerful systems.
- Some Java applications use native code through the Java Native Interface (JNI), where the native code is 64-bit. For example, the Java Database Connectivity (JDBC) driver is written in 64-bit native code on a 64-bit platform.
- Some Java applications require other improved capabilities of 64-bit systems.
The Java API and porting native code

The previous diagram is helpful for identifying significant components and for understanding what needs to change when porting applications from 31-bit to 64-bit. All Java applications are written to a defined Java application programming interface (API). This API is the same for the 31-bit and 64-bit versions of the Java platform.
The Java API includes the Java class libraries (for example, net, lang, io, and rmi) that are a fundamental part of the Java platform. The Java API, and all of the Java code, is exactly the same on a 64-bit implementation as it is on a 31-bit implementation. Therefore, if you have Java application code that runs on a 31-bit Java system, it runs unchanged on a 64-bit system.
Many Java applications are not written 100% in the Java language. For these applications, some of their code is written in a non-Java language, such as C or C++, which is generally referred to as “native code”. Porting Java applications that have native code takes more effort.
All Java code (the application and the class libraries) is executed by the Java Virtual Machine (Java VM). The Java VM contains subcomponents that run the Java code and manage the data in the Java Heap. The J9 VM includes a just-in-time compiler (JIT) that compiles the Java code into native processor instructions before execution. This compilation process maximizes the performance of the code.
In a 64-bit implementation of the Java environment, it is the Java VM that is implemented as a 64-bit program and that is aware of the 64-bit nature of the underlying processor. This includes the JIT compiler, which must compile the Java code to use 64-bit addresses. The JIT compiler is also aware of the full 64-bit instruction set available on the underlying processor.
The Java VM communicates with the operating system through the Host Porting Interface (HPI). This communication makes the Java VM code independent of the underlying operating system and allows the IBM® implementation of the Java platform to support a range of operating systems on a given processor type.
JNI and native code
The Java VM, the HPI layer, and the Java code all execute within a single 64-bit operating system process. Normally, there is some native code that executes within that same process. The native code is one or more libraries of code compiled directly for the processor and operating system. The native code is accessed from Java code through the Java Native Interface (JNI). The native code can also access Java objects and methods through the JNI. Some native code is part of the J2SE implementation, such as the code that implements the Java rmi classes using the remote procedure call functions provided by the operating system. Other native code may be provided as part of an application.
There is one other interface which is similar to the JNI: the Java Virtual Machine Tool Interface (JVMTI). This interface provides capabilities for profiling and debugging Java applications. To use these capabilities, you must write some native code.
In the case of the 64-bit implementations of the Java platform, all native code that is associated with the 64-bit Java VM must be 64-bit, because it all runs in the same process space as the Java VM. It is not possible to run 64-bit code and 31-bit code within the same process space because of the incompatibility of the address sizes between these two types of code.
Native code, typically written in the C or C++ languages, is directly aware of the size of addresses. If your application has native code, the native code must be modified to work correctly with the differences in 64-bit environments, such as 64-bit addresses. Finally, native code must also be recompiled and relinked for the 64-bit system.
In summary, the 64-bit Java VM implementation runs on a 64-bit processor and links to code that is also 64-bit “aware”. The Java VM is also able to use the large memory support and 64-bit instructions of the underlying processor. The Java applications it runs are exactly the same as those that can run on 31-bit implementations of Java. Only native code must be ported from 31-bit systems to 64-bit systems.
The advantage of Java programs when moving from 31-bit to 64-bit
The Java language and environment make the transition from 31-bit computing to 64-bit computing straightforward. For programs written in other languages that have explicit address pointers, such as C and C++, porting an application from 31-bit to 64-bit can take considerable effort. This is because every pointer must be redeclared as a 64-bit quantity and any calculation concerning addresses must be checked carefully and adjusted to ensure that it executes correctly in the 64-bit environment. By contrast, 100% Java applications do not even require to be recompiled in order to run correctly in the 64-bit environment. For Java applications, all the hard work is done by the Java VM implementation, while the underlying pointer size is hidden from view.