A class file is a structured binary document containing bytecode and metadata that let the JVM load, verify, link, and execute a class or interface.

Learning Question

What is actually inside a .class file?

A class file is not just compressed Java source code. It is also not final machine code for the CPU.

It is a JVM-defined binary format. The JVM can read it to understand what type is being defined, what members it has, what bytecode implements its methods, and what symbolic references it uses.

The first mental model is:

A class file is the JVM’s portable, loadable representation of a type and its executable method bodies.

The Major Parts

At a high level, a class file contains:

PartRole
Magic and versionIdentify the file as a class file and state the class file version
Constant poolStores symbolic references, names, descriptors, strings, numbers, and other constants
Access flagsRecord modifiers such as public, final, interface, abstract, or enum-related properties
This class and super classIdentify the type being defined and its direct superclass
InterfacesList directly implemented interfaces
FieldsDescribe field names, descriptors, access flags, and attributes
MethodsDescribe method names, descriptors, access flags, bytecode, and attributes
AttributesStore additional metadata such as code, line numbers, annotations, signatures, and bootstrap method data

The exact format is detailed and strict. The practical point is that the JVM receives a structured type definition, not source text.

Bytecode Lives Inside Method Code

Executable method bodies are usually stored in Code attributes attached to methods.

For a simple method:

int add(int a, int b) {
    return a + b;
}

the class file does not store the expression in that source form. It stores bytecode instructions that use the JVM execution model. Conceptually, the method body means:

load local variable a
load local variable b
add the two int values
return the int result

The real bytecode is more compact and uses specific instruction names, local variable slots, and stack operations. The important point is that bytecode is already below Java source, but still above CPU machine code.

The Constant Pool

The constant pool is one of the most important parts of a class file.

It stores many things indirectly:

  • class and interface names
  • field references
  • method references
  • string literals
  • numeric constants
  • type descriptors
  • bootstrap method references used by some dynamic features

Many bytecode instructions do not directly contain full target information. They refer to constant-pool entries. Those entries can later be resolved by the JVM during linking or execution.

This is why class files can contain symbolic references such as “call this method on that class” before the JVM has converted those references into concrete runtime links.

Descriptors and Metadata

The JVM uses descriptors to represent field and method types.

For example, a method that takes two int values and returns an int has a descriptor like:

(II)I

This notation is not how Java programmers write methods, but it is compact and precise for the JVM.

Class files may also contain metadata that is useful for tools and runtime behavior:

  • source file names
  • line number tables
  • local variable tables
  • annotations
  • generic signatures
  • inner class metadata

Some of this metadata is required for correct execution. Some is optional or tool-facing. A stack trace can show source line numbers only when useful line-number metadata is available.

What a Class File Is Not

A class file is not the same thing as source code.

It may not preserve source comments, formatting, local variable names, or every source-level construct in the way the programmer wrote it.

A class file is also not the same thing as machine code.

Bytecode instructions are defined for the JVM execution model. A JVM implementation may interpret them, compile them into machine code, inline them, optimize them, or deoptimize them later. The class file remains the portable representation that starts the runtime process.

Inspecting a Class File

The common tool for inspecting class files is javap.

For example:

javap -c -v Example

The -c option shows bytecode. The -v option shows more detailed class-file metadata, including the constant pool.

The goal is not to memorize every instruction. The value is seeing the boundary: Java source becomes a structured artifact with bytecode, descriptors, symbolic references, and metadata.

Core Mental Model

Keep these boundaries separate:

  • A class file defines a type in a binary JVM format.
  • Bytecode is stored inside method code attributes.
  • The constant pool stores symbolic information that bytecode can refer to.
  • Metadata supports linking, verification, reflection, debugging, annotations, and tooling.
  • The JVM loads class files and turns their contents into runtime structures.

Final Summary

A class file contains the JVM-loadable definition of a type: bytecode, names, descriptors, symbolic references, fields, methods, and metadata.

It is the bridge between Java source compilation and JVM runtime execution.