Object-Oriented COBOL

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; an upcoming 4th edition is in ballot), in which the object-oriented facilities come from COBOL 2002; against IBM Enterprise COBOL for z/OS 6.5 (PTFs through September 2026) on z/OS 3.2, whose Language Reference and Programming Guide still document OO syntax built around Java; and against GnuCOBOL 3.2 (28 July 2023, the latest release), which does not implement the OO syntax: that was tested with cobc on 2026-10-20 and the real diagnostics are shown below. The only program on this page that was compiled with cobc -x -Wall (and with -std=ibm, without warnings) and run is the plain-COBOL substitute near the end. The OO classes and clients are labelled "z/OS; not run here" and are checked against the Language Reference and the Programming Guide. The Rocket Visual COBOL material is described from the vendor’s public documentation and was not run.

Object-oriented COBOL is the least used part of the language, and this page says so plainly. It explains the model so that the keywords and the manuals make sense, shows what a Circulation BOOKITEM class looks like on z/OS, says what each product does and does not support, and gives a procedural design that achieves the same encapsulation in every compiler. Subprograms, which are the usual alternative, are on Subprograms, CALL and Linkage; user-defined functions and prototypes are on User-Defined Functions and Prototypes; calling C, Java and Python without objects is on Interoperability with C, Java and Python; and the reference data types behind USAGE OBJECT REFERENCE are listed with the other usages on USAGE and Numeric Representation. The compiler differences are collected on Compilers and Dialects.

Where the book is outdated: Taulli’s Modern Mainframe Development (2022, chapter 7) names OO COBOL among the ways COBOL meets other languages. The Enterprise COBOL manuals since version 6.4 describe a second, non-OO route to Java (the JAVAIOP option, the JAVA-CALLABLE directive and the cjbuild utility), and version 6.5 changed how cjbuild names its output DLL. A reader who learns Java interoperability only from the OO chapter therefore misses the route IBM now documents first for existing programs. The book is cited from its publisher page only and no text from it is reproduced.

The COBOL 2002 object model

COBOL 2002 added classes and objects to a language that had only programs and data items. The model is the common one, spelled with COBOL’s usual verbosity.

Concept COBOL form

Class

A source unit that starts with CLASS-ID and ends with END CLASS. One class per source file on Enterprise COBOL.

Instance data

The DATA DIVISION of the OBJECT definition. Every instance gets its own copy.

Instance method

A METHOD-ID unit inside the OBJECT definition. It runs on one instance and sees that instance’s data.

Factory data and factory methods

The FACTORY definition, the equivalent of static members in Java. They belong to the class, are shared, and are invoked on the class name.

Object reference

A data item with USAGE OBJECT REFERENCE class-name, which holds a reference to an instance. A universal reference (no class name) can refer to any object.

Creating an instance

INVOKE class-name NEW RETURNING reference on Enterprise COBOL. The standard describes creation as invoking a predefined factory method of the class.

Calling a method

INVOKE reference "method-name" USING ... RETURNING .... The method name is a case-sensitive literal or an identifier that holds one.

Inheritance

CLASS-ID. Child INHERITS FROM Parent. A class has exactly one parent: COBOL has single inheritance.

SELF and SUPER

Two ways to name the object a method is running on. SELF dispatches normally. SUPER starts the lookup above the current class, so a subclass can call the parent’s version of a method it overrides.

Interface

INTERFACE-ID defines method signatures and a class declares IMPLEMENTS interface-name. This is in the 2002 standard model; see the product sections below for who supports it.

The next diagram shows the Circulation example used on this page: a BOOKITEM class with a factory side (a count shared by the whole class) and an object side (the copies of one book), and a subclass that specializes it. The base of every Enterprise COBOL class is java.lang.Object, which is what makes the classes visible to Java.

classDiagram class JavaLangObject { java.lang.Object } class BOOKITEM { FACTORY: ITEMS-CREATED OBJECT: BOOK-COPIES FACTORY method CREATED-COUNT OBJECT method checkOut OBJECT method giveBack OBJECT method describe } class RAREBOOK { OBJECT method describe overrides } JavaLangObject <|-- BOOKITEM : INHERITS BOOKITEM <|-- RAREBOOK : INHERITS

Class structure on Enterprise COBOL

The Language Reference describes the class definition as a fixed outline, and the Programming Guide describes each part as a task.

  • A class header: an IDENTIFICATION DIVISION with the CLASS-ID paragraph, which names the class and its single parent with INHERITS. A COBOL class inherits, directly or indirectly, from java.lang.Object; the parent can itself be written in Java.

  • An ENVIRONMENT DIVISION whose CONFIGURATION SECTION holds the REPOSITORY paragraph. The paragraph is required: it relates the class names used in the source to their external names, such as java.lang.Object. An INPUT-OUTPUT SECTION is not allowed at class level and goes in the individual methods that need it.

  • An optional FACTORY definition, ended by END FACTORY, with its own IDENTIFICATION DIVISION, a DATA DIVISION for the shared data and a PROCEDURE DIVISION of factory methods.

  • An optional OBJECT definition, ended by END OBJECT, built the same way for instance data and instance methods.

  • END CLASS.

Each method starts with an IDENTIFICATION DIVISION and a METHOD-ID paragraph naming the method as a quoted literal, ends with END METHOD, and has its own LINKAGE SECTION and a PROCEDURE DIVISION with USING and RETURNING. Method names are case-sensitive and follow Java’s rules for method names, because Java clients call them by that name. Settings in the SOURCE-COMPUTER, OBJECT-COMPUTER or SPECIAL-NAMES paragraphs of the class apply to every method. Each class definition must be in a separate source file.

The Circulation BOOKITEM class (z/OS; not run here)

This is an original class written for this page and checked against the structure above; it was not compiled, because there is no Enterprise COBOL compiler in the test environment. Every item in it follows the shapes shown in the Programming Guide for the Account example. The copies counter is binary because the class can be called from Java.

       IDENTIFICATION DIVISION.
       CLASS-ID. BookItem INHERITS FROM Base.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
           CLASS Base IS "java.lang.Object"
           CLASS BookItem IS "BookItem".
      *
       IDENTIFICATION DIVISION.
       FACTORY.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  ITEMS-CREATED       PIC S9(9) BINARY VALUE 0.
       PROCEDURE DIVISION.
      *
       IDENTIFICATION DIVISION.
       METHOD-ID. "createdCount".
       DATA DIVISION.
       LINKAGE SECTION.
       01  LK-COUNT            PIC S9(9) BINARY.
       PROCEDURE DIVISION RETURNING LK-COUNT.
           MOVE ITEMS-CREATED TO LK-COUNT.
       END METHOD "createdCount".
       END FACTORY.
      *
       IDENTIFICATION DIVISION.
       OBJECT.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  BOOK-COPIES         PIC S9(9) BINARY VALUE 1.
       PROCEDURE DIVISION.
      *
       IDENTIFICATION DIVISION.
       METHOD-ID. "checkOut".
       DATA DIVISION.
       LINKAGE SECTION.
       01  LK-LEFT             PIC S9(9) BINARY.
       PROCEDURE DIVISION RETURNING LK-LEFT.
           IF BOOK-COPIES > 0
               SUBTRACT 1 FROM BOOK-COPIES
           END-IF
           MOVE BOOK-COPIES TO LK-LEFT.
       END METHOD "checkOut".
      *
       IDENTIFICATION DIVISION.
       METHOD-ID. "giveBack".
       DATA DIVISION.
       LINKAGE SECTION.
       01  LK-LEFT             PIC S9(9) BINARY.
       PROCEDURE DIVISION RETURNING LK-LEFT.
           ADD 1 TO BOOK-COPIES
           MOVE BOOK-COPIES TO LK-LEFT.
       END METHOD "giveBack".
       END OBJECT.
       END CLASS BookItem.

The factory side is where an implementation would increment ITEMS-CREATED each time an instance is made, typically from a factory method that the class defines for construction; the example keeps only the reader method to stay short.

Clients: INVOKE, NEW, SELF and SUPER

A client is a program (or another class) that creates instances and calls their methods. It lists the classes it uses in its own REPOSITORY paragraph and holds instances in object reference items.

A client program (z/OS; not run here)

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CIRCCLI.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
           CLASS BookItem IS "BookItem".
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  BK                  USAGE OBJECT REFERENCE BookItem.
       01  COPIES-LEFT         PIC S9(9) BINARY.
       PROCEDURE DIVISION.
           INVOKE BookItem NEW RETURNING BK
           INVOKE BK "checkOut" RETURNING COPIES-LEFT
           DISPLAY "Copies left: " COPIES-LEFT
           INVOKE BK "giveBack" RETURNING COPIES-LEFT
           DISPLAY "Copies left: " COPIES-LEFT
           STOP RUN.

The rules of INVOKE that matter in practice:

  • INVOKE class-name NEW RETURNING reference creates an instance. RETURNING is required. For a Java class USING selects the constructor; for a COBOL class USING must not be specified.

  • INVOKE reference "name" calls an instance method. With a class name instead of a reference, the method must be a factory method (COBOL) or a static method (Java).

  • Arguments are passed BY VALUE only. There is no BY REFERENCE or BY CONTENT in INVOKE, which is a real difference from CALL.

  • ON EXCEPTION runs when the object or class has no method with a matching signature. Without it, a severity-3 Language Environment condition is raised. NOT ON EXCEPTION runs after the method returns, and END-INVOKE makes the statement usable inside a conditional.

  • INVOKE does not set RETURN-CODE.

  • Dynamic-length items cannot be operands, the statement is not supported when the LP(64) option is in effect, and it cannot call AMODE 64 Java methods.

SELF and SUPER are used only inside a method. INVOKE SELF "checkOut" calls a method on the current object, honouring any override in a subclass. INVOKE SUPER "describe" also acts on the current object but starts the method lookup above the current class, so an overriding describe in RAREBOOK can call the describe of BOOKITEM and then add its own text. A subclass overrides an instance method by defining a method with the same signature.

Interfaces and polymorphism

The 2002 standard model has two ways to get polymorphism: inheritance (a RAREBOOK can be used wherever a BOOKITEM is expected, by declaring the reference as USAGE OBJECT REFERENCE BookItem) and interfaces (INTERFACE-ID and IMPLEMENTS, which describe behaviour without data). The Enterprise COBOL class-structure page does not mention INTERFACE-ID or IMPLEMENTS, and its model is a single parent class that can be a Java class; this page therefore does not show interface syntax for z/OS and treats interfaces as part of the standard model only. Check the manual of the product you use before relying on them.

IBM’s Java-based OO COBOL on z/OS

Enterprise COBOL’s OO syntax exists mainly to interoperate with Java. The Language Reference says the syntax lets a program define classes, create instances, invoke methods and inherit from Java or COBOL classes. In effect a COBOL class compiles to something the Java virtual machine can load, with java.lang.Object at the root of its inheritance chain.

Aspect Rule in the 6.5 manuals

Threads

Java programs can be multithreaded and send asynchronous signals, so mixing COBOL with Java requires the THREAD compiler option.

CICS

OO programs that use Java interoperability cannot contain EXEC CICS statements or run in CICS.

SQL

COBOL classes cannot contain EXEC SQL or EXEC SQLIMS statements.

AMODE 64

The OO framework is not supported with the LP(64) option or with AMODE 64 Java.

Environment

The Programming Guide recommends developing and running OO COBOL and Java programs in the z/OS UNIX environment.

Wrapping existing code

COBOL classes can call procedural COBOL programs, so a class can be a wrapper that lets Java code reach existing COBOL logic.

Other Java access

Further capabilities come from calling Java Native Interface (JNI) services.

Those restrictions are the heart of the story. The Circulation shop’s valuable code is batch, Db2 and CICS code; a class that cannot hold SQL or run in CICS can only be a thin shell around it, and calling a Java class from a CICS COBOL program through the OO framework is excluded outright.

Non-OO Java interoperability in 6.4 and 6.5

Enterprise COBOL 6.4 introduced a second route that needs no classes. The compiler generates stub files from ordinary COBOL programs (marked callable from Java with the JAVA-CALLABLE directive, selected by the JAVAIOP compiler option), and the cjbuild utility builds those stubs into a DLL. Programs call static Java methods with an enhanced CALL, and Java calls COBOL programs through the generated glue. The Programming Guide describes it as a more comprehensive and flexible form of COBOL/Java interoperability than the OO framework, built so that existing COBOL programs can take part with little change. Version 6.5 changed how cjbuild names its DLL when it writes to a data set (the LIB prefix is no longer added, so a full 8-character member name can be used, with JCL link-step changes), and a 2026 PTF added support for a newer Java release. When the Java version is 25 or higher the manual also asks for the --enable-native-access=ALL-UNNAMED JVM option, set through the COBJVMINITOPTIONS environment variable for COBOL-started applications.

This is why the OO route is rarely the right start today, and it is the answer to the question this page keeps asking. IBM has not removed the OO syntax from 6.5: the Language Reference and Programming Guide still document it. But for a shop that wants a COBOL program to call Java or be called from Java, the non-OO route works on programs as they are, so there is no need to wrap logic in classes, and it is the one that receives the new options and PTF attention. Use the OO syntax when you need what only it offers: subclassing a Java class in COBOL, or implementing an object that Java code treats as an instance. The full non-OO story, with the build steps, is on Interoperability with C, Java and Python. This sentence is an assessment of the documentation, not a statement by IBM that the OO syntax is deprecated; the manuals do not say that.

Rocket Visual COBOL on .NET and the JVM

Rocket Software acquired the application-modernization business of Micro Focus, whose Visual COBOL product it continues. Its approach is different from IBM’s: instead of an OO layer on a COBOL run time, the compiler can target a managed runtime. The product documentation calls the result managed COBOL, a collective term for COBOL compiled to .NET (used from Visual Studio) and COBOL compiled to the JVM (used from Eclipse). Managed COBOL has its own syntax for classes, methods, inheritance and access levels and reaches the framework class library of the platform through INVOKE and SET verbs. Procedural COBOL, compiled to native code, is documented separately in the vendor’s COBOL language reference and can be called from managed code. The Rocket documentation site is https://docs.rocketsoftware.com/ and is the place to read the manuals for the release you have; this page names no release because the vendor pages could not be verified for a current one. The practical consequence is that OO COBOL in practice means a Rocket or earlier Micro Focus shop writing .NET or Java applications in COBOL syntax, not a z/OS shop.

GnuCOBOL and OO COBOL

GnuCOBOL 3.2 does not implement the OO syntax. This was tested rather than assumed. The class below (the BOOKITEM outline with only its object data and one method) was given to cobc from GnuCOBOL 3.2.0:

       IDENTIFICATION DIVISION.
       CLASS-ID. BOOKITEM INHERITS FROM BASE.
       ENVIRONMENT DIVISION.
       OBJECT.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-COPIES  PIC 9(3) VALUE 0.
       PROCEDURE DIVISION.
       METHOD-ID. GET-COPIES.
       DATA DIVISION.
       LINKAGE SECTION.
       01  LS-COPIES  PIC 9(3).
       PROCEDURE DIVISION RETURNING LS-COPIES.
           MOVE WS-COPIES TO LS-COPIES
           GOBACK.
       END METHOD GET-COPIES.
       END OBJECT.
       END CLASS BOOKITEM.

Compiled with cobc -x -Wall (and again with -std=ibm and -std=mf, which gave the same first error and a second error that differs only in adding "(Area A)" under -std=ibm), the compiler stops at the first line:

oo1.cob:2: error: 'CLASS-ID' is a reserved word, but isn't supported
oo1.cob:2: error: syntax error, unexpected Identifier, expecting FUNCTION-ID or PROGRAM-ID

The compiler knows the words, which is why the first message says "reserved word" and not "syntax error", but treats them as unsupported. The list printed by cobc --list-reserved marks these as not implemented:

CLASS-ID                        No
INTERFACE-ID                    No
INVOKE                          No
METHOD-ID                       No
OBJECT-REFERENCE                No
SELF                            No
SUPER                           No

A client with a CLASS entry in the REPOSITORY paragraph fails as well: in 3.2 that paragraph accepts FUNCTION entries (see User-Defined Functions and Prototypes) and the first CLASS line is a syntax error. Within the 3.2 behaviour tested here, the answer for GnuCOBOL is therefore: no classes, no methods, no INVOKE, no object references. The result is specific to GnuCOBOL 3.2.0 on the day of the test; the project’s own documentation, linked below, is the place to check a later release, and this page does not claim anything about unreleased versions.

The same design in plain COBOL

The useful part of a class is encapsulation: state that only a fixed set of operations can touch. A subprogram gives that in every compiler. WORKING-STORAGE in a called program keeps its values between calls, and a request code selects the operation. The next two programs build the Circulation BOOKITEM that way. The first is the "class", with BOOKREC as its private state; the second is a client that creates the item, checks it out twice, returns it and shows it.

      * BOOKITEM - a book "object" built from plain COBOL: private state
      * in a subprogram, public operations selected by a request code.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. BOOKITEM.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
           COPY BOOKREC.
       LINKAGE SECTION.
       01  LK-REQUEST          PIC X(4).
           88  REQ-CREATE      VALUE "NEW ".
           88  REQ-CHECKOUT    VALUE "OUT ".
           88  REQ-RETURN      VALUE "BACK".
           88  REQ-SHOW        VALUE "SHOW".
       01  LK-BOOK-ID          PIC 9(6).
       01  LK-TITLE            PIC X(30).
       01  LK-COPIES           PIC 9(3).
       01  LK-RESULT           PIC 9.
           88  REQ-OK          VALUE 0.
           88  REQ-REFUSED     VALUE 1.
       PROCEDURE DIVISION USING LK-REQUEST LK-BOOK-ID LK-TITLE
                                LK-COPIES LK-RESULT.
       MAIN-PARA.
           SET REQ-OK TO TRUE
           EVALUATE TRUE
               WHEN REQ-CREATE
                   MOVE LK-BOOK-ID TO BOOK-ID
                   MOVE LK-TITLE   TO BOOK-TITLE
                   MOVE LK-COPIES  TO BOOK-COPIES
               WHEN REQ-CHECKOUT
                   IF BOOK-COPIES > 0
                       SUBTRACT 1 FROM BOOK-COPIES
                   ELSE
                       SET REQ-REFUSED TO TRUE
                   END-IF
               WHEN REQ-RETURN
                   ADD 1 TO BOOK-COPIES
               WHEN REQ-SHOW
                   DISPLAY BOOK-ID " " BOOK-TITLE " " BOOK-COPIES
               WHEN OTHER
                   SET REQ-REFUSED TO TRUE
           END-EVALUATE
           MOVE BOOK-COPIES TO LK-COPIES
           GOBACK.
       END PROGRAM BOOKITEM.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. BOOKMAIN.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-REQUEST          PIC X(4).
       01  WS-BOOK-ID          PIC 9(6) VALUE 1.
       01  WS-TITLE            PIC X(30) VALUE "BATCH PROCESSING".
       01  WS-COPIES           PIC 9(3) VALUE 1.
       01  WS-RESULT           PIC 9.
           88  CALL-OK         VALUE 0.
       PROCEDURE DIVISION.
       MAIN-PARA.
           MOVE "NEW " TO WS-REQUEST
           PERFORM DO-REQUEST
           MOVE "OUT " TO WS-REQUEST
           PERFORM DO-REQUEST
           MOVE "OUT " TO WS-REQUEST
           PERFORM DO-REQUEST
           MOVE "BACK" TO WS-REQUEST
           PERFORM DO-REQUEST
           MOVE "SHOW" TO WS-REQUEST
           PERFORM DO-REQUEST
           STOP RUN.
       DO-REQUEST.
           CALL "BOOKITEM" USING WS-REQUEST WS-BOOK-ID WS-TITLE
                                 WS-COPIES WS-RESULT
           IF CALL-OK
               DISPLAY WS-REQUEST " ok, copies " WS-COPIES
           ELSE
               DISPLAY WS-REQUEST " refused, copies " WS-COPIES
           END-IF.

Compiled together with cobc -x -Wall -I. bookmain.cob bookitem.cob (and with -std=ibm), no warnings, it prints:

NEW  ok, copies 001
OUT  ok, copies 000
OUT  refused, copies 000
BACK ok, copies 001
000001 BATCH PROCESSING               001
SHOW ok, copies 001

The second checkout is refused because no copy is left, the behaviour that the OO checkOut method expresses with its IF. What the plain design does not give is what objects give: several independent instances at once (this subprogram holds one book; a table of book records with the request code taking an index is the usual extension), inheritance (there is no RAREBOOK) and method dispatch chosen at run time. For most batch work none of that is needed. The same pattern works on z/OS under Enterprise COBOL, where the called program also keeps its WORKING-STORAGE between calls unless it is declared INITIAL.

Why OO COBOL saw little adoption

Adoption was low and the reasons can be read from the facts above. This section is an assessment, not a measurement: the manuals and the public record do not publish usage figures.

  • The standard arrived late. COBOL 2002 was published years after Java and C++ had settled the object-oriented mainstream, and the products implemented it unevenly. A language whose main use is long-lived code gets a decade of delay for free.

  • The value was already in programs and data. Existing COBOL is batch and transaction code built from programs, copybooks and files. Wrapping it in classes adds a layer without changing what it does, and the largest part of the estate cannot use the OO framework anyway (no EXEC SQL, no CICS).

  • Compilers do not agree. IBM ties OO COBOL to Java and the JVM; Rocket’s managed COBOL ties it to .NET or the JVM; GnuCOBOL has none. Code written for one cannot move to another, which is the opposite of what portability-minded COBOL shops want.

  • Restrictions and cost. The THREAD requirement, the AMODE 64 limits, the Java setup and the z/OS UNIX recommendation make the OO route heavier than a CALL.

  • A lighter alternative appeared. The non-OO interoperability of 6.4 and 6.5 and, in other places, web services and the JSON features of JSON GENERATE and PARSE connect COBOL to Java without classes.

  • Verbosity. The syntax is long, and a skilled COBOL team gains little from INVOKE BK "checkOut" RETURNING COPIES-LEFT over CALL "BOOKITEM".

The result is that OO COBOL is mostly met as inherited code in a few Visual COBOL and Java-integration projects. Nothing here suggests starting a new z/OS batch system with it. When you do meet it, the sections above map the keywords to the manuals.

Common mistakes

  • Compiling a class with GnuCOBOL. CLASS-ID, METHOD-ID and INVOKE give "reserved word, but isn’t supported" in 3.2. Use a procedural design, or a vendor compiler for the OO dialect.

  • Passing arguments BY REFERENCE to INVOKE. On Enterprise COBOL arguments to INVOKE are passed BY VALUE only.

  • Forgetting RETURNING on INVOKE ... NEW. The phrase is required, and USING is not allowed for COBOL classes.

  • Wrong case in a method name. Method names are case-sensitive literals; "checkout" does not find "checkOut", and without ON EXCEPTION a severity-3 condition is raised.

  • Putting EXEC SQL or EXEC CICS in a class. Neither is allowed in an Enterprise COBOL OO program that uses Java interoperability; keep that code in procedural programs and let the class call them.

  • Omitting THREAD. Mixing COBOL with Java requires the THREAD compiler option.

  • Reaching for OO to call Java. For most existing programs, the non-OO interoperability of 6.4 and 6.5 is the simpler route.

  • Combining several classes in one source file. Each COBOL class definition must be in its own file.