technical: How to Call HLASM from Java
Java and High Level Assembler (HLASM) are often regarded as the Montagues
and Capulets of z/OS. However there are occasions where you need to call an
HLASM program from Java. This article shows how.
Introduction
High Level Assembler (HLASM) has been around in one form or another from the
birth of the z/Series mainframe. And because of this, there is a huge amount
of legacy HLASM code still being used by mainframe users. What's more, there
are still some things that are best done in HLASM - from z/OS user exits to
performance critical code.
Java is almost the exact opposite. The new kid on the block, Java on z/OS has
yet to gain much traction. However Java programmers with no z/OS experience
can now develop new code, and even port existing programs to z/OS. This makes
Java a very appealing option.
But what if you need to call an HLASM program from Java? There could be many
reasons for this, such as:
- There is an existing HLASM routine that you want to call from Java.
- You need to call another z/OS routine, and need an HLASM routine to sit
in-between to handle incompatible parameters and environments.
- You need to get some z/OS information that isn't available to Java.
- You need to do something that you can't do in Java.
This article will show how this is done by providing an example. We will have
an HLASM routine that can return either:
- the z/OS host name (or more specifically, the z/OS SMFID that identifies
the name of the z/OS image), or
- the Sysplex name.
This routine will be called from a Java program that provides a parameter.
This parameter will determine whether the host name or Sysplex name is returned.
To do this we will actually have four programs:
- The HLASM routine: ASMINF.
- The Java Native Interface (JNI) routine: JNIzOS.c - written in C.
- The Java program zOSInfo - providing the classes needed to call our interface.
- The Java program callHlasm- a program to test our interface.
1. The HLASM Program ASMINF
Program Description
This program will be passed a parameter holding the address of one 8 byte area.
On input, this area will hold either:
- HOST - requesting the z/OS host name.
- SYSPLEX - requesting the Sysplex name.
If neither of these values is present, the routine will exit with a return
code of 8.
The routine will insert the host or Sysplex name in this same area, and will
exit with a return code of 0.
ASMINF Listing
*============================================================
*
* ASMINF - Provide z/OS Host or Sysplex Name
*
*============================================================
ASMINF EDCXPRLG PARMWRDS=1,BASEREG=R10,EXPORT=YES
L R9,0(R1) R9 -> Input area
* -----------------------------------------------------------
* Check the value of our input area, and get Sysplex/Host
* as required
* -----------------------------------------------------------
CLC 0(7,R9),=C'SYSPLEX' Getting sysplex?
BE SYSPLEX Yes - Go get it
CLC 0(4,R9),=C'HOST' Getting host?
BE HOST Yes - Go get it
LA R3,8 Else Bad Return Code
B EXIT
* -----------------------------------------------------------
* Get the Host Name from the SMCA Control Block
* -----------------------------------------------------------
HOST DS 0H
LLGT R2,CVTPTR R1 -> CVT
LLGT R2,CVTSMCA-CVT(R2) R2 -> SMCA
MVC 0(L'SMCASID,R9),SMCASID-SMCABASE(R2) SMFID
B EXIT0 And Exit
* -----------------------------------------------------------
* Get the Sysplex Name from the Extended CVT
* -----------------------------------------------------------
SYSPLEX DS 0H
LLGT R2,CVTPTR R2 -> CVT
MVC 0(L'ECVTSPLX,R9),ECVTSPLX-ECVT(R2) Sysplex
B EXIT0 And Exit
* -----------------------------------------------------------
* Zero Return Code and Exit
* -----------------------------------------------------------
EXIT0 DS 0H
XR R3,R3 Zero Return Code
EXIT DS 0H
EDCXEPLG Return to caller
* -----------------------------------------------------------
* Mapping Macros and DSECTs
* -----------------------------------------------------------
CVT DSECT=YES Map CVT
IHAECVT Map ECVT
IEESMCA Map SMCA
|
ASMINF Explanation
- This program accesses standard z/OS control blocks to get the information
required:
- CVT (Common Vector Table) to get addresses of other control blocks.
- ECVT (Extended CVT) to get the Sysplex name.
- SMCA (SMF Control Area) to get the host name.
More information about these control blocks can be found in the relevant
IBM z/OS Data Area manuals.
- From Java SDK 1.4, all Java JNI calls expect to call an XPLINK module. This
means our HLASM program must be XPLINK. To achieve this:
- The program starts with the EDCXPRLG macro and finishes with EDCXEPLG.
These macros are similar to the Language Environment (LE) CEESTART and
CEETERM macros, and are documented in the IBM z/OS C/C++ Programming Guide.
- ASMINF adheres to the XPLINK register usage conventions
- Our module passes the return code back in R3, which is returned to C.
- ASMINF can be called in either 31 or 64 bit mode. However 31 bit programs
cannot call 64 bit modules, or vice versa. So ASMINF must be in the same addressing
mode as the JNI module calling it. The only way to achieve this is to have
two HLASM modules:
- ASMINF - 31 bit
- ASMINF64 - 64 bit
ASMINF64 will look like:
ASMINF64 CELQPRLG PARMWRDS=1,BASEREG=R10,EXPORT=YES
LG R9,0(R1) R9 -> Input area
(same code as for ASMINF)
* ----------------------------------------------------
* Zero Return Code and Exit
* ----------------------------------------------------
EXIT0 DS 0H
XR R3,R3 Zero Return Code
EXIT DS 0H
CELQEPLG Return to caller
|
This is identical to ASMINF except for the CELQPRLG and CELQEPLG macros (and
the 64 bit load of the parameter address). These macros do exactly the same
job as EDCXPRLG and EDCXEPLG - and their parameters are the same. They are
documented in the IBM z/OS Language Environment Programming Guide for 64-bit
Addressing Mode manual.
- The 31 bit ASMINF has been coded to be 64 bit compliant in all other ways.
For example the LLGT instruction has been used instead of LA when loading
the (31 bit) pointers to the ECVT and SMCA control blocks from the CVT control
block.
Assembling ASMINF
Because ASMINF is an XPLINK module it needs to be a DLL. This means that we
will be assembling with the RENT and GOFF HLASM options.
Binding ASMINF
If ASMINF is going to be called statically then there's no need to bind it
- that's done when binding JNIzOS. However if called dynamically then it must
be bound as a DLL, and you must save the side file for use with JNIzOS.
2. The JNI Program JNIzOS
Program Description
JNIzOS is a C program that sits between our Java classes and ASMINF. It accepts
a string parameter from Java, passes this onto ASMINF, and passes back the value
returned by ASMINF.
If the return code from ASMINF is not zero (meaning that an error has occurred),
then JNIzOS returns the string "(invalid)" to its Java caller.
JNIzOS Listing
/* ------------------------------------------------------
Java declaration
------------------------------------------------------ */
JNIEXPORT jstring JNICALL Java_zOSInfo_showZos
(JNIEnv *, jobject, jstring);
/*========================================================
Mainline Code
======================================================== */
JNIEXPORT jstring JNICALL
Java_zOSInfo_showZos(JNIEnv *env,jobject obj,jstring jParm)
{
/* --- Variables ------------------------------------- */
int rc; /* rc from ASMINF */
char *passarea; /* ptr to parms */
/* --- Get the parm input, and convert to EBCDIC ---- */
const char* msg=(*env)->GetStringUTFChars(env,jParm,0);
__atoe((char*) msg);
(*env)->ReleaseStringUTFChars(env, jParm, msg);
/* --- Setup 8 Byte Area to pass (leave space for NULL)*/
passarea = malloc(10); /* Get area */
memset(passarea, 0, 10); /* Clear area */
strcpy(passarea,msg); /* Put parm in */
/* --- Load the correct JNI module: 31 or 64 bit ---- */
# ifdef _LP64
rc = ASMINF64(&passarea);
#else
rc = ASMINF(&passarea);
#endif
/* --- If bad return code from HLASM, modify passarea */
if (rc > 0) strcpy(passarea, "(invalid)");
/* --- Convert area returned by HLASM back to ASCII - */
__etoa((char*) passarea);
/* --- And return it --------------------------------- */
return (*env)->NewStringUTF(env, passarea);
} /* main */
|
JNIzOS Explanation
JNIzOS is a standard Java JNI program with some special features:
- It uses the __atoe and __etoa functions to convert between EBCDIC and ASCII.
These functions use the default Locale. We convert the parameters passed from
Java to EBCDIC, and the values from ASMINF to ASCII.
- It does a standard call to the HLASM program - using the _LP64 macro to
determine which HLASM program to call, the 31 or 64 bit version.
- We again have the problem where 31 bit programs can't call 64 bit programs
and vice versa. So once again there will be two versions of this code:
- JNIzOS - 31 bit version
- JNIzOS64 - 64 bit version.
We can use the same code, but use the LP64 compiler option for the 64 bit version.
Compiling JNIzOS
- As JNIzOS is an XPLINK module, the XPLINK compiler option must be used.
- If not compiling with the EXPORTALL function, then a #pragma statement looking
like:
#pragma export(Java_zOSInfo_showZos)
|
is needed. Without this, our Java class won't find the zOSInfo function.
Binding JNIzOS
If dynamically calling ASMINF:
- The side file generated by ASMINF must be specified as additional input
to the binder
- ASMINF must exist in a place that can be loaded by JNIzOS. Or in other words,
in either the z/OS linklist, STEPLIB or libpath. Because this can at times
be difficult and prone to errors, it may be more robust to statically call
ASMINF.
Additionally:
- JNIzOS must be bound as an XPLINK dll.
- If running Java SDK 1.5 or later, the module name JNIzOS is fine. However
if we are running an earlier Java SDK, this name must be in the format libxxxxx.so
- for example libJNIzOS.so.
- JNIzOS and JNIzOS64 must be bound into a USS directory in the Java libpath.
It cannot be bound in the z/OS linklist or STEPLIB - Java won't find it. You
can get around this is by defining an external link in the USS directory that
points to the module in the z/OS linklist or STEPLIB. The USS ln command can
do this.
The Java Program zOSInfo
Program Description
zOSInfo holds the classes connecting to our JNI module. Standard Java code,
it uses the system property com.ibm.vm.bitmode to determine if running in 31
bit (the value is actually 32) or 64 bit mode. If running Java SDK 1.5 or later,
the more standard sun.arch.data.model property can also be used here.
zOSInfo Listing
/* -------------------------------------------------------
callHlasm - Call ASMINF HLASM module from Java
------------------------------------------------------ */
class zOSInfo {
public native String showZos(String parm);
static {
/* --- Get our addressing mode (31 or 64) ----- */
String arch =
System.getProperty("com.ibm.vm.bitmode");
/* --- Load the correct JNI Module ------------ */
if (arch.equals("64"))
System.loadLibrary("JNIzOS64");
else
System.loadLibrary("JNIzOS");
}
}
|
The Java Program callHlasm
Program Description
This program tests our interface. We will call zOSInfo three times, each with
a different parameter:
- SYSPLEX - to return the Sysplex name
- HOST - to return the z/OS SMFID
- JUNK - an invalid parameter. Our program will return "(invalid)"
callHlasmSample Listing
/* -------------------------------------------------------
callHlasm - Call ASMINF HLASM module from Java
------------------------------------------------------ */
class callHlasm {
public static void main(String[] args) throws Exception {
System.out.println("(callHlasm) Started:");
zOSInfo a = new zOSInfo();
/* --- Get Hostname ------------------------------ */
System.out.print("Host: ");
System.out.println(a.showZos("HOST"));
/* --- Get Sysplex Name: ------------------------- */
System.out.print("Sysplex: ");
System.out.println(a.showZos("SYSPLEX"));
/* --- Specify an invalid parameter -------------- */
System.out.print("Bad Parm: ");
System.out.println(a.showZos("JUNK"));
System.out.println("(callHlasm) Finished");
}
}
|
Conclusion
To be able to call an HLASM module can be invaluable for Java programmers,
and it isn't difficult to do. In fact the most difficult part is probably making
your HLASM module XPLINK compliant.
References
David Stephens
|