|
Frequently Asked Questions
Please let me know if you have additional questions and I'll add them here.
Java on OS/390
How can I tell if Java is installed on my OS/390?
The easiest way is to just ask your systems programmer! If that doesn't suit you, have a look in the HFS. You can navigate the HFS most easily by typing ishell at TSO or in PDF option 6. Java is usually installed in the /usr/lpp/java/J1.x directory. Assuming that this where java is installed, make sure that the bin subdirectory is in your PATH environment variable. You can check this by typing
echo $PATH
or
printenv PATH
while in the OMVS shell. If the bin subdirectory to the J1.x directory is not in your path, enter the following command in the OMVS shell:
export PATH=/usr/lpp/java/J1.x/bin:$PATH
Then, to actually verify the version of Java which is installed, type the following into the OMVS shell:
java -fullversion
A string like the following should appear:
java full version "J2RE 1.3.1 IBM OS/390 Persistent Reusable VM build hm131s-20020723"
Or, you can type
java -version
and you'll receive something like:
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1)
Classic VM (build 1.3.1, J2RE 1.3.1 IBM OS/390 Persistent Reusable VM build hm131s-20020723 JIT enabled: jitc))
How do I get a copy of Java for OS/390?
You can order the code on a tape from IBM or you can download the code. For more details, visit the IBM web page for Java for OS/390.
Can I create executable code with Java for OS/390?
Java for OS/390 creates java bytecodes which are not directly executable OS/390 instructions. They are a bytecode for a virtual machine which must be "executed" or interpreted by that virtual machine. IBM used to have an offering that allowed you to take that bytecode file and turn it into actual executable object code. This was called "Visual Age for Java, Enterprise Edition for OS/390." It was product 5655-JAV. This is not to be confused with "Visual Age for Java, Enterprise Edition for Windows" which was an IDE that ran on a Windows desktop. This is also not to be confused with Java for OS/390 which is IBM's port of Sun's JDK. The similarity of the names makes this very confusing but they are, in fact, three distinct products. The native compiler available for Visual Age for Java, Enterprise Edition for OS/390 was also called HPJ (High Performance Java) sometimes. The native compiler is no longer available. Major advances in the JIT compiler have obviated the need for a static native compiler.

How do I compile a Java program in batch?
Here is some JCL for doing this.
How do I execute a Java program in batch?
Here is some JCL for doing this.
How do I debug my Java for OS/390 programs?
There are two ways to use debuggers for your Java programs on OS/390. The first way, the jdb debugger, allows you to debug OS/390 java bytecode from OS/390 USS. Using this option, you only need Java for OS/390. You do not need any other software. The other way, discussed in greater detail below, makes use of a standard called JPDA or the Java Platform Debugging Architecture.
 Under the USS itself, you can use the jdb command which comes with the Java Development Kit as part of Java for OS/390. Although documention for the jdb debugger can be found here, the Sun documentation lists only a few of the commands. Type jdb under the shell to start the debugger and then type help for the full list of commands. The jdb command is a command-line debugging tool, analogous to dbx, though not nearly as powerful. If you're compiling from the command line using the javac command, be sure to specify the -g option to generate the debugging information need for jdb and the other debuggers. When compiling from an IDE, check to make sure if there is an option to include debugging information in the .class files. When exporting a class file to OS/390, be sure select the option to include debug information in the class file, if appropriate.
 The OS/390 JVMs are JPDA-compliant JVMs so you can use any JPDA compliant debugger. An excellent visual debugger is built into Eclipse. Before I used Eclipse, I used BugSeeker from Karmira, which is also excellect and very reasonably priced. Most IDEs today include a JPDA-compliant debugger as part of the IDE.
What environment variables are used by the JVM?
I've pieced some of this information together so be sure to test anything before you rely on it. Not all of these environment variables are available in all releases. Also, IBM service has a number of environment variables that produce traces used for debugging the JVM and the JIT compiler. They will advise you when to set these environment variables. I've discovered the following:
 JAVA_HOME
This is the base directory for your Java for OS/390 installation. It is the directory where the java command is located. Our value for JAVA_HOME is /usr/lpp/java/IBM/J1.3. You don't need to set this environment variable up yourself. If you don't have it set up, the java command will set it up for you.
 JAVA_COMPILER
Turns off the JIT (just-in-time) compiler or allows you to substitute an alternate JIT compiler. The JIT must be turned off when debugging with the Remote Debugger.
 CLASSPATH
This is the regular Java CLASSPATH variable used by all versions of the JVM. It is used as a search path for Java classes. It consists of a list of directories and/or jar files and/or zip files separated by colons.
 LIBPATH
This isn't really a JVM environment variable but rather a USS environment variable. It contains a list of directories separated by colons that is used as a search path when loading DLLs under from the HFS. This is important when you have native code compiled as DLLs loaded with System.loadLibrary(). See the C/C++ Programming Guide for more information.
 LD_LIBRARY_PATH
This also contains a search path for DLLs under from the HFS. I'm not really sure how it's different from LIBPATH yet but for some things it needs to be set. LD_LIBRARY_PATH is used on some versions of Unix in place of LIBPATH but I'm not sure how much it's needed on the mainframe.
 _CEE_RUNOPTS
Contains Language Environment runtime options separated by a space. If this variable is set before java is invoked from the shell, these options will override those compiled into java by IBM as well as any installation or IBM defaults that would apply. Use this cautiously.
 _BPXK_MDUMP
Also not part of the JVM but part of USS itself. This was first introduced in OS/390 v2r7. It can specify the name of an MVS or HFS file. If the filename starts with a /, it is assumed to be an HFS file. This indicates the location to which a SYSMDUMP should be written when running under USS. If the value is "OFF", the SYSMDUMP will be in the current working directory with a filename of coredump.pid where pid is the process id.
 IBM_JAVA_ZOS_TDUMP
Modern versions of the JVM take a TDUMP when the JVM detects a problem. Setting this environment variable to NO prevents that from happening. For more complete information, see information APAR II13292.
 IBM_JAVA_ZOS_TDUMP_PATTERN
This environment variable is set to a string which is a pattern for the dump dataset name in case the default name of the TDUMP dataset does not conform with your shop standards.
 IBM_JAVA_ZOS_TDUMP_COUNT
This limits the number of TDUMPs that are requested. For example, if an error occurs during CEEDUMP processing, it could result in two dumps. The default for this value is 2.
Interfacing between Assembler-COBOL-PL/I Programs and Java
How do I communicate between Java programs and non-Java programs?
Java defines a standard feature for the Java platform called the Java Native Interface ( JNI). This is a series of APIs and rules which allow communication between Java programs and non-Java programs. Remember that the JVM is free to internally represent data and methods (a String, for example) in any way that it feels like, as long as the results of defined operations work out correctly. Therefore, JNI makes no assumptions about how Java fields or methods are stored internally. JNI allows access to Java fields and methods in a standard way so that you can use the values in native programs. IBM has an example of how to write a simple JNI program for OS/390. The Sun Java website has valuable information on the JNI in general. If you really want to get into this, as I have, I strongly recommend that you get yourself a copy of Sheng Liang's excellent book.
Although all JVMs are required to support the JNI, a particular JVM is also permitted to implement its own, possibly more efficient, non-portable techniques for accessing Java objects. As far as I know, the IBM JVM for OS/390 does not yet implement any native access other than the JNI. Using the JNI will allow your native programs to operate properly with any JVM which runs under OS/390.
How do I call from Java to an Assembler program?
While Java native methods can be directly implemented by C or C++ programs, there is no supported way to implement a native method directly in Assembler, COBOL, PL/I, or Fortran. Since the JVM is written in C and C++, it uses C and C++ calling conventions when calling external programs. Therefore, you will need some C "glue" code which connects the Java native method to the Assembler program.
The C code is included in a program object created with the DLL binder option so that the Java_xxx entrypoints can be located dynamically by the JVM when it goes to call the native method. Note that although the C code is defined as a DLL to the binder, it doesn't need to be compiled with the DLL compiler option unless it, in turn, calls DLLs. That is, the DLL compiler option tells the compiler to generate calls which can be resolved by a DLL. It doesn't have anything to do with callers of the C program.
So far, I have called Assembler programs from C programs using static linking. Here is an example of such a combination.
Can I call an AMODE 24 Assembler program from C?
Yes, absolutely. I use a small assembler program that is called from C. That program takes a pointer to the real program to call and a pointer to a save area that is "below the line", in addition to the arguments to be passed on to the target assembler program.Then, it saves the original mode, switches modes and calls the target program. On return, it switches modes back to the original mode. Things look a little funny in the CEEDUMP but I can usually find what I need.
How do I use packed decimal values in a Java program?
In Java, the best way to represent decimal numbers is by using the com.ibm.math.BigDecimal class. It is included with all IBM JVMs (including the one for OS/390 and z/OS) and provides a superior decimal implementation over java.math.BigDecimal. JSR13 proposes to make this a part of Java itself. To convert numbers to BigDecimal from a byte array containing a packed decimal number, I use a routine that travels down the byte array and builds a StringBuffer to pass to the BigDecimal constructor. I'm going to experiment with some other techniques that may be more efficient but that is what I'm using for now.
|