JVM Classfile Format

Last update: 2024-11-18 19:52:43 +0800 +0800
Available translations: 日本語 / 中文(简体) / 中文(繁體)

A class file is a big-endian binary structure consumed by the JVM. It begins with 0xCAFEBABE, followed by u2 minor and major versions. A JVM accepts only the versions defined for its implementation; class-file parsers must reject unsupported versions rather than assume that a newer file is backward-compatible.

Top-Level Structure #

After the magic and version, the file contains:

  1. constant_pool_count and the indexed constant-pool entries;
  2. class access_flags, this_class, and super_class;
  3. interface indexes;
  4. field_info structures;
  5. method_info structures; and
  6. class-level attribute_info structures.

Counts are unsigned u2 values, except an attribute’s attribute_length, which is u4. Access flags describe the context: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, and ACC_MODULE are not all meaningful or legal for every class-file kind.

Constant Pool and Names #

The constant pool is indexed from one; index zero is invalid except where a specific structure reserves it. CONSTANT_Long and CONSTANT_Double consume two consecutive indexes, with the second unusable. Entries include primitive and string constants; Class; String; field, method, and interface-method references; name-and-type pairs; method handles and method types; dynamic and invoke-dynamic call sites; modules; and packages. References are symbolic: for example, a CONSTANT_Methodref points through a class and name-and-type entry instead of an in-memory method.

Class-file names use slash-separated internal names such as java/lang/String; a binary name in source-oriented APIs uses dots. Field and method descriptors encode types, for example Ljava/lang/String;, [I, and (I[Ljava/lang/String;)V. CONSTANT_Utf8 uses the class-file modified UTF-8 encoding, which encodes the null character as C0 80 and represents UTF-16 surrogate code units individually. It is not interchangeable with a generic UTF-8 decoder.

Members and Attributes #

Each field_info and method_info has access flags, name and descriptor indexes, and an attribute table. A method’s Code attribute stores max_stack, max_locals, bytecode, exception handlers, and nested attributes such as line numbers or stack-map frames. Fields may carry ConstantValue; classes and members carry metadata through attributes, including annotations, signatures, nest information, records, modules, and debugging data. Unknown attributes may be skipped only by using their declared length; their semantics cannot be guessed from their name.

Safe Parsing #

Treat a class file as hostile input even when it originates from a build. Before every read, validate the remaining byte count; validate every count, index, tag, flag combination, descriptor, and attribute length; use checked arithmetic for offset plus length; and reject trailing structural inconsistencies. Enforce the format’s version and context rules before resolving symbolic references. The verifier adds execution-safety checks, but it is not a substitute for a bounded binary parser.

Tools such as javap -v display a decoded view, but transformations should use a maintained library that supports the target class-file version and preserves unknown attributes where required.

References #

Comments

Read or comment on GitHub (sign-in required to comment)