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:
| Part | Role |
|---|---|
| Magic and version | Identify the file as a class file and state the class file version |
| Constant pool | Stores symbolic references, names, descriptors, strings, numbers, and other constants |
| Access flags | Record modifiers such as public, final, interface, abstract, or enum-related properties |
| This class and super class | Identify the type being defined and its direct superclass |
| Interfaces | List directly implemented interfaces |
| Fields | Describe field names, descriptors, access flags, and attributes |
| Methods | Describe method names, descriptors, access flags, bytecode, and attributes |
| Attributes | Store 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 resultThe 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)IThis 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 ExampleThe -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.