J2VMS: Exploiting OpenVMS from Java

J2VMS: Exploiting OpenVMS from Java

User's Guide & Release Notes

This manual covers installation, trouble shooting and release information for J2VMS, an interface for communicating between native OpenVMS and Java.

Revision/Update Information: This is a new manual.

Operating System and Version: OpenVMS Alpha Version 7.3-2

OpenVMS I64 Version 8.2

Software Version: J2VMS Version 1.3

Java for OpenVMS Version 1.2 or higher

November 2008

OpenVMS is a trademark of Hewlett-Packard Development Company. L.P.

Java is a trademark of Sun Microsystems. Inc.

Copyright ©2001-2002 Jim Brankin

Copyright ©2008 Kednos Enterprises



Manual Objectives

This manual attempts to describe, as completely as possible, the J2VMS calling interface.

Intended Audience

This manual is designed for programmers who are developing Java applications that must communicate directly with OpenVMS System Services and Run-Time Libraries (including customer libraries).

It is expected that readers will have a working knowledge of software design and development. It is encouraged that the reader also explore some of the Java documentation pointers included below.

Document Structure

This manual contains the following chapters

Associated Documents

The following documents may be useful when using J2VMS.
Java2 1.3.1 SE API Specification
J2VMS V1.3 API Specification
Optimizing Java Technology Software Performance on HP OpenVMS.
BLISS Language Reference Manual
Guide to HP Structure Definition Language

On-Line Examples

A collection of examples programs are present on line in SYS$COMMON:[SYSHLP.EXAMPLES.J2VMS]. (This device-directory specification may have been given the logical name J2VMS$EXAMPLES during installation of the J2VMS software kit.)

Reader's Comments

Kednos welcomes your comments on this manual. Please send any comments, corrections, etc. to either of the following addresses:
Email pli-support@kednos.com
Postal Mail Kednos Enterprises
Suite 7, 220 Country Club Drive
Pacific Grove, CA 93950

This section contains release information on J2VMS. Release information is necessary for gaining the best results from J2VMS. It is recommended that all users read this information.

J2VMS Version V1.3

Overview of Changes

J2VMS Version 1.3 contains the following enchancements and fixes:

Overview of Restrictions

J2VMS Version 1.3 contains the following restrictions:

Chapter 1
Getting Started

This chapter covers the installation and removal of J2VMS including software and hardware dependencies.

1.1 Software Prerequisites

The following software is required to successfully install and use J2VMS:

It is also recommended that all available software patches be applied to these products prior to attempting installation.

For improved performance later versions of the JDK are also recommended. Later versions include support for FastVM and other significant performance improvements.

1.2 Hardware Requirements

The only hardware requirement is that the system be either an Alpha or Integrity system as J2VMS (like Java) is only available on OpenVMS Alpha and I64.

Be aware that Java is particullarly resource hungry so older, slower machines will often perform poorly, particularly in interactive environments. The general rule of thumb is, the more memory and the faster the CPU the better Java applications will perform. There are some documents available that offer hints and tips for performance improvements. Details of these can be found under the section Associated Documents.

1.3 Installation

The J2VMS software product kit presents a number of options to the installer to control exactly what is installed. Table 1-1 describes each of these options and their defaults. Example 1-1 shows an example of an installation of the J2VMS product.

Table 1-1 J2VMS Installation Options
Description Default
User Guide & Release Notes in PostScript format Yes
User Guide & Release Notes in PDF format Yes
User Guide & Release Notes in HTML format Yes
J2VMS API Specification Yes
Example programs Yes

Example 1-1 J2VMS Product Installation

The following product has been selected: 
    KEDNOS VMS J2VMS V1.3                  Layered Product 
Do you want to continue? [YES] YES 
Configuration phase starting ... 
You will be asked to choose options, if any, for each selected product and for 
any products that may be installed to satisfy software dependency requirements. 
KEDNOS VMS J2VMS V1.3: Java Interface to Native OpenVMS 
    Copyright © 2001-2002 Jim Brankin, 2008 Kednos Enterprises 
    Kednos Enterprises 
    This product uses the PAK: J2VMS 
Do you want the defaults for all options? [YES] NO 
    Install J2VMS Documentation? [YES] YES 
    Do you want the defaults for all suboptions? [YES] NO 
      Install the J2VMS V1.3 API Specification [YES] YES 
      Install J2VMS User Guide & Release Notes in HTML format? [YES] YES 
      Install J2VMS User Guide & Release Notes in PDF format? [YES] YES 
      Install J2VMS User Guide & Release Notes in PostScript format? [YES] YES 
    Install example programs? [YES] YES 
Do you want to review the options? [NO] NO 
Execution phase starting ... 
The following product will be installed to destination: 
    KEDNOS VMS J2VMS V1.3                  DISK$AXP082:[VMS$COMMON.] 
Portion done: 0%...10%...20%...30%...70%...90%...100% 
The following product has been installed: 
    KEDNOS VMS J2VMS V1.3                  Layered Product 
KEDNOS VMS J2VMS V1.3: Java Interface to Native OpenVMS 
    Relase Notes are included in the user guide. 
    J2VMS release notes are included in the User Guide & Release Notes 
    manual. To install these locally ensure that at least one documentation 
    option is selected. Otherwise, the manual can be found at the Kednos 
    Insert the following lines in SYS$MANAGER:SYSTARTUP_VMS.COM: 

1.4 Post Installation

Once the J2VMS software product kit has been installed it is advisable to add the startup procedure, SYS$STARTUP:J2VMS$STARTUP.COM to the system startup prodcedure. Althought it is not necessary in this kit, it may become so in a later release. It als defines the J2VMS$EXAMPLES logical and installs the SYS$LIBRARY:J2VMS$SHR.EXE image.

1.5 Removal

Removal of the software product is a case of using the PCSI PRODUCT REMOVE command. There is no provision in this release for clean up of the API Specification in this kit (it is expected this will change in a future release). If the API spec was unpacked it will have to be removed manually.

Example 1-2 demonstrates removal of the J2VMS product.

Example 1-2 J2VMS Product Removal

The following product has been selected: 
    KEDNOS VMS J2VMS V1.3                  Layered Product 
Do you want to continue? [YES] YES 
The following product will be removed from destination: 
    KEDNOS VMS J2VMS V1.3                  DISK$AXP082:[VMS$COMMON.] 
Portion done: 0%...40%...50%...60%...70%...80%...100% 
The following product has been removed: 
    KEDNOS VMS J2VMS V1.3                  Layered Product 

Chapter 2
Developing An Application

This chapter covers the different parts of the J2VMS interface and how It has been deliberately written to draw comparisons between native coding and coding in Java using J2VMS. The intention is that it will be easier to understand for someone who has more background in native languages such as PL/I, BASIC, C and Pascal.

2.1 Includes

The first item to cover is how to make the J2VMS interface available to a Java program. It is quite simple and is tackled in two steps. The first is configuring the Java classpath. Without this the Java compiler and interpreter will not be able to find the J2VMS classes. The example below demonstrates how to include that J2VMS library in the JAVA$CLASSPATCH logical.


Another way to configure the Java classpath is to include it on the command line as shown in this example:

$ java -classpath "/sys$library/j2vms$vs.jar:..." ... 

For more information on configuring the Java classpath, please consult the relevant Java for OpenVMS user guide.

Once the compiler and interpreter can find the J2VMS class library the relevant classes need to be included in the source module. It is recommended that the base vs package be included in it's entirety. It it not normally recommended to include external packages in this way. However, the vs package is not made up of many classes.

When it comes to including the different modules within STARLET it is best to only include those classes that are necessary. There are many modules in the vs.starlet package. This will cause unnecessary memory usage and increase compile and load time significantly.

The example below demonstrates the best way to include the vs package and the STARLET modules SS and STS.

import vs.*; 
import vs.starlet.SS; 
import vs.starlet.STS; 

2.2 External Routines

In order for J2VMS to call native routines they first need to be declared. This can be likened to declaring a routine in C with the extern attribute or declaring an external entry in PL/I. The difference in Java is that there is no linker to process the external declarations and locate the relevant shared image. Therefore the caller needs to know which shareable image the routines exists in.

The external declaration is constructed using the SystemCall. class. This class is a simplified method for calling the LIB$ Run-Time Library routine LIB$FIND_IMAGE_SYMBOL (sometimes referred to as LIB$FIS). LIB$FIND_IMAGE_SYMBOL dynamically loads shareable images by looking up symbols.

Declaring An External Reference to LIB$PUT_OUTPUT

The following example below demonstrates how to declare the external routine LIB$PUT_OUTPUT (found in SYS$LIBRARY:LIBRTL.EXE) in Java. It also includes examples in C, PL/I and BASIC for comparison.

SystemCall lib$put_output = new SystemCall("LIB$PUT_OUTPUT", "LIBRTL"); 

The same declaration in C


extern int lib$put_output(); 

The same declaration in PL/I


declare lib$put_output entry(any, any) returns(fixed binary(31)); 

The same declaration in BASIC


external integer function lib$put_output 

The Structure Definition Language (SDL) can be used to generate external routine declarations also. These classes can then be used in the same way as the classes vs.SystemServices and vs.LibRoutines. These classes are covered further in Section 2.4.

2.3 Argument Passing Mechanisms

Before discussing the actual call mechanism between J2VMS and native OpenVMS it is important to first cover argument passing. J2VMS provides a set of classes that allow the caller to pass arguments in the common language environment, just as they would a native language. These classes are:

Passing arguments using J2VMS can be likened to constructing an argument list for the LIB$ Run-Time Library function LIB$CALLG. An array of pointers and/or values is constructed and passed to the target routine using LIB$CALLG as a catalyst (originally high level language access to the VAX CALLG instruction). J2VMS is quite similar. However, it has it's minor differences mostly related to the object oriented architecture of Java.

J2VMS argument lists are constructed as an array of objects from the abstract class vs.VMSparam. Unlike an argument list destined for LIB$CALLG there is no need for the argument count in the first element as the size of the array is known, thanks to Java. This means that all elements in the argument list detail arguments. Each element consists of an argument mechanism class (shown above) that informs J2VMS as to exactly how it's own argument is to be passed. When J2VMS actually performs the call it determines the mechanism by comparing class types and then allocating internal storage as necessary. Copying between internal storage and Java class storage before and after the actual native call.

vs.VMSparam Argument List for LIB$CHAR


StringBuffer result = new StringBuffer(); 
Byte code = new Byte((byte) 65); 
vs.VMSparam arglst = new VMSparam[] { new ByDesc(result), 
                                      new ByRef(code) }; 

The LIB$ Run-Time Library routine LIB$CHAR accepts two arguments. The first is a result string, passed by descriptor, and the second is a byte containing an 8-bit ASCII character code.


declare arglst(2) pointer; 
declare 1 result, 
        2 dsc$w_length fixed binary(15), 
        2 dsc$b_dtype fixed binary(7), 
        2 dsc$b_class fixed binary(7), 
        2 dsc$a_pointer pointer; 
declare result_str character(dsc$w_length) based(dsc$a_pointer); 
declare code fixed binary(7); 
result.dsc$w_length = 0; 
result.dsc$b_dtype = DSC$K_DTYPE_T; 
result.dsc$b_class = DSC$K_CLASS_D; 
result.dsc$a_pointer = null(); 
arglst(1) = addr(result); 
arglst(2) = addr(code); 

The above snippet of PL/I code attempts to demonstrate the actions of the code above in a native language. In this example the string descriptor for result is constructed explictly to show what J2VMS does internally when dealing with an argument passed by descriptor.

The following sections cover each of the mechanisms in close. These sections must be read carefully as there are one or two caveats that must be observed. For full documentation of what data types each passing mechanism class can deal with, please consult the J2VMS API Specification. This documentation ships with the software product and is available at the Kednos website. See Associated Documents for more details.

2.3.1 Passing Arguments By Descriptor

The class vs.ByDesc is used to inform J2VMS that it's argument should be passed by descriptor. Many data types can be passed by descriptor. However, probably the most used are vs.Cmem, java.lang.StringBuffer and byte[]. Both vs.Cmem and byte[] result in fixed length descriptors of type DSC$K_CLASS_S. java.lang.StringBuffer is a special case. It results in a dynamic string descriptor with a type of DSC$K_CLASS_D. Prior to a call the content of the StringBuffer object is copied into a dynamic descriptor. Then following the return from the call the string descriptor is copied back into the StringBuffer object so the result it can be used in the Java environment.

All objects and arrays passed by descriptor can be used to receive results, with one exception. The vs.ByDesc constructor for the java.lang.String object cannot be used to receive a result. This is a restriction imposed by Java, not J2VMS. There is no public method for updating the contents of a String object. In the case where a string object is passed by descriptor it results in a new byte array being allocated and the contents of the String object being copied into it. The example below demonstrates what actually happens.

Example 2-1 shows a literal java.lang.String object being passed to the LIB$ Run-Time Library routine LIB$PUT_OUTPUT. This example demonstrates the convenience of being able to pass string literals and have them built "in the argument list".

Example 2-1 Passing a java.lang.String Object by Descriptor

lib.lib$put_output(new VMSparam[] { 
                       new ByDesc("hello, " + "world") 

However, it is not possible to receive data into a String object. Example 2-2 is a complete program that can be copied and executed to demonstrate the restriction. This example is also available from the Kednos website, or online at SYS$COMMON:[SYSHLP.EXAMPLES.J2VMS]GET2.JAVA.

Example 2-2 Receiving String Data From A Called Routine

import java.lang.*; 
import vs.*; 
public class get2 
    public static void main(String[] args) 
        Short result_len = new Short((short) 0); 
        String result1 = new String(); 
        StringBuffer result2 = new StringBuffer(); 
        LibRoutines lib = new LibRoutines(); 
        System.out.println("Storage before any calls to LIB$PUT_OUTPUT"); 
        System.out.println("  * result_len = " + result_len); 
        System.out.println("  * result1 = <" + result1 + ">"); 
        System.out.println("  * result2 = <" + result2 + ">"); 
        lib.lib$get_input(new VMSparam[] { 
                              new ByDesc(result1), 
                              new ByDesc("String result>> "), 
                              new ByRef(result_len) 
        System.out.println("Storage after first call to LIB$PUT_OUTPUT"); 
        System.out.println("  * result_len = " + result_len); 
        System.out.println("  * result1 = <" + result1 + ">"); 
        System.out.println("  * result2 = <" + result2 + ">"); 
        lib.lib$get_input(new VMSparam[] { 
                              new ByDesc(result2), 
                              new ByDesc("String result>> "), 
                              new ByRef(result_len) 
        System.out.println("Storage after second call to LIB$PUT_OUTPUT"); 
        System.out.println("  * result_len = " + result_len); 
        System.out.println("  * result1 = <" + result1 + ">"); 
        System.out.println("  * result2 = <" + result2 + ">"); 

Table 2-1 summarises the native usage of Java object types passed by descriptor.

Table 2-1 Summary of Native Usage of Java Objects Passed by Descriptor
Java Class/Primitive Type Descriptor Class Writable
byte[] Static (DSC$K_CLASS_S) Yes
int[] Static (DSC$K_CLASS_S) Yes
long[] Static (DSC$K_CLASS_S) Yes
short[] Static (DSC$K_CLASS_S) Yes
java.lang.Byte Static (DSC$K_CLASS_S) Yes
java.lang.Integer Static (DSC$K_CLASS_S) Yes
java.lang.Long Static (DSC$K_CLASS_S) Yes
java.lang.Short Static (DSC$K_CLASS_S) Yes
java.lang.String Static (DSC$K_CLASS_S) No
java.lang.StringBuffer Dynamic (DSC$K_CLASS_D) Yes
vs.Cmem Static (DSC$K_CLASS_S) Yes
vs.VmsStruct Static (DSC$K_CLASS_S) Yes


There is currently no support for passing arrays by descriptor in the same way as other native high level languages. Currently all arrays of primitive types are treated as byte[] arrays. However, support is planned in a future release.

Next Contents