Introduction
The Oak class file is the class file of Java before JDK 1.0.2, with the versions 45.0, 45.1 and 45.2. Oak was the language’s name until 1995, and an OpenJDK developer later called these files “Oak classes”. Each holds one compiled class: its constant pool, fields and methods, and each method’s bytecode for the Java Virtual Machine.
The format differs from the later class file in one structure. In each method’s
Code attribute, max_stack and
max_locals are one byte each and code_length is two bytes, so
the attribute’s header is 4 bytes instead of 8. Everything else is laid out as in the
class files that followed: the same constant pool, flags, fields, methods, exception
table and attributes.
No specification of this layout survives, and the Java Virtual Machine Specification has never described it. It is known from the class file reader of HotSpot, the JVM of OpenJDK, which read it in every JDK up to 13, and from the OpenJDK bug reports that removed it in JDK 14. The specification says that JDK 1.0.2 supported versions 45.0 to 45.3, so a file of version 45.0 to 45.2 may also be laid out the later way; such files are not this format.
A .class file dropped on any page of this site opens in the explorer,
which shows every structure in it, a disassembly in the style of javap and
the constant pool as a table.
Structure
A class file is one big-endian structure, read from start to end.
0magicCA FE BA BE4 bytes4minor_version, major_version: 45.0, 45.1 or 45.24 bytes8constant_pool_count, then the constant pool, with tags 1 to 12varies…access_flags, this_class, super_class, interfaces8 bytes and 2 per interface…fields: a count, then each field with its attributesvaries…methods: a count, then each method with its Code attributevaries…attributes of the class, such asSourceFilevaries
The Code header
The first fields of a Code attribute’s body, after its name and length:
| Offset | Size | Type | Name |
|---|---|---|---|
| 6 | 1 | u1 | max_stack |
| 7 | 1 | u1 | max_locals |
| 8 | 2 | u2 | code_length |
| 10 | code_length | u1[] | code |
So a method may use at most 255 stack places and 255 local variable slots. HotSpot’s reader, as published in the JDK 8 sources, has this branch, with the comment “max_stack, locals and length are smaller in pre-version 45.2 classes” beside its length check:
// Stack size, locals size, and code size
if (_major_version == 45 && _minor_version <= 2) {
cfs->guarantee_more(4, CHECK_(nullHandle));
max_stack = cfs->get_u1_fast();
max_locals = cfs->get_u1_fast();
code_length = cfs->get_u2_fast();
} else {
cfs->guarantee_more(8, CHECK_(nullHandle));
max_stack = cfs->get_u2_fast();
max_locals = cfs->get_u2_fast();
code_length = cfs->get_u4_fast();
}
classFileParser.cpp in OpenJDK 8uDespite the comment, the test covers 45.2 itself: every version from 45.0 to 45.2.
History
- 1995 and early 1996: Java’s pre-release compilers write class files of versions 45.0 to 45.2. Later readers expect this Code layout in all of them; whether every file of the time used it, and which releases wrote which minor version, is not recorded.
- 1996: JDK 1.0.2 writes version 45.3, with two-byte
max_stackandmax_localsand a four-bytecode_length, the layout the specification describes. - JDK 1.2 to 13: HotSpot reads 45.0 to 45.2 files with the 4-byte Code header. This also means it turns down 45.0 to 45.2 files that follow the specification.
- JDK 14 (2020): OpenJDK removes the old reader (bug JDK-8232890, “Remove bad Code attribute parsing code”). The bug says such files predate Java and that the layout was never in the specification. From then on every file is read the specification’s way, and an Oak file fails to load.
- Apache BCEL has an open issue, BCEL-341, about the same layout.
Telling it apart
The explorer’s parser for this format checks that the file starts with
CA FE BA BE, that the major version at offset 6 is 45 and the minor version
at offset 4 is 0, 1 or 2. It then reads every Code attribute with the 4-byte header,
accepts only constant pool tags 1 to 12, and reads only the attributes JDK 1.0.2 knew:
ConstantValue, Code, Exceptions, SourceFile, LineNumberTable and LocalVariableTable.
Any other attribute is shown as bytes.
The explorer tries the Java class file
parser first. On a file in this format it reads the 4-byte header as 8 bytes, finds a
code_length made of the first bytes of code, which runs far past the end
of the attribute, and turns the file down. Only then is this parser tried. A 45.0 to
45.2 file whose Code attributes add up the later way is read as a Java class file.
Variants
- Java class file – versions 45.3 to 72, JDK 1.0.2 to Java SE 28, as the JVM Specification describes
- Oak class file (45.0 to 45.2) – pre-release classes whose Code attribute has a one-byte max_stack and max_locals
Links
Software
- OpenJDK – the Java platform, whose HotSpot virtual machine loaded this layout up to JDK 13 (Windows, macOS, Linux)
Reference
- classFileParser.cpp (JDK 8u) – HotSpot’s class file reader with the branch for this layout
- JDK-8232890 – “Remove bad Code attribute parsing code”, the bug that removed the layout in JDK 14
- JDK-8232967 – its parent issue, which notes that spec-conforming 45.0 to 45.2 files were turned down
- The OpenJDK commit – the change that removed the old reader
- compiler-dev, August 2024 – a discussion of “oak” class files on the OpenJDK mailing list
- core-libs-dev, January 2025 – “Oak classes with u1 max stacks and locals”
- BCEL-341 – Apache BCEL’s issue about the same layout
- The class File Format – the JVM Specification’s chapter 4, which describes the later layout