Modernization efforts have encouraged mainframe developers to use functions that exist on non-z/OS platforms. Java, one of the more modern programming languages, is in wide use on several computing platforms. Its write-once, run-anywhere ability makes it suitable to run on z/OS. Application developers can use the Java Native Interface (JNI) to execute Java methods from other languages, or invoke non-Java code from Java. Using the JNI is complicated and using it on z/OS adds another level of complexity. Part of this comes from the interesting split in z/OS, where we have the traditional MVS environment and the newer UNIX System Services (USS) environment. Also, there are many program creation and execution options that have an impact on using the JNI on z/OS.
Many Websites and manuals describe using the JNI, but none provide a complete example of its use on z/OS. The code needs to be explained as well as the Job Control Language (JCL) to compile and execute the modules and the compile and run-time options.
This article is the result of research performed prior to rewriting a significant portion of an existing product and additional work performed while involved in a modernization project. The initial work was Java-to-C-to-Assembler. The example here goes in the other direction. The main takeaway for readers is an approach to combining existing code to new development. This can be valuable in situations where you have applications running in more than one environment, but use platform-specific development methods. Any new code can be written in Java and existing programs can use the JNI to invoke the new functionality.
A compressed file is available at http://home.comcast.net/~wffalby/JNI_on_zOS_files.zip. It contains the program source files, the JCL to create and run the executable modules, a script file to compile the Java program, and text files showing the output from the programs, the Java Virtual Machine (JVM), and the Java class disassembler. The programming examples show a z/OS assembler program calling into a C module that invokes Java methods. The glue code—the C module—runs on z/OS. The Java code runs under USS. You should have these files handy as you read the rest of this article.
To get the most out of this article, readers should have experience writing code in the z/OS environment, be familiar with the three languages used in the examples, have experience with inter-language communications on z/OS, be cognizant of USS, and have the necessary permissions and resources to compile and run the Java code.
Let’s begin with a brief definition of the JNI. Everything described here is documented in several manuals and on various Websites. We’ve pulled it together and provided working examples, as many of us understand concepts better when we see them in practice.
What is JNI?
According to the Java Website (http://java.sun.com/j2se/1.5.0/docs/guide/jni/index.html), the JNI “is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform.” JNI is the glue between Java and non-Java applications. To create this glue, you use C or C++ as the intermediate language between Java and whatever other language you’re using.
The Assembler Code
The Assembler program creates the High-Level Language (HLL) environment, calls into the C module to create the JVM, invokes a Java method, calls into the C module to destroy the JVM, and then terminates the HLL environment.