ByteScope

Java class file format

Compiled Java bytecode, executed by the JVM.

MIME type
application/java-vm
Extensions
.class
Category
Executables & bytecode

Magic-number signature

0x00000000CAFEBABE····'CAFEBABE' magic

About the Java class file format

A .class file is one compiled Java type — a class, interface, enum or record — in the JVM's own container format, and almost all of it is one structure: the constant pool. Class names, method names, field descriptors, string literals and every symbolic reference live there as numbered entries, and the rest of the file refers to them by index rather than by text. That is why a class file is so compressible inside a JAR, why renaming a class changes bytes all over the file, and why every offset after the constant pool is variable: the pool's length depends entirely on how many names the type mentions.

Header layout, byte by byte

OffsetLengthFieldMeaning
04magicCA FE BA BE, chosen by James Gosling before Java had a name and shared, awkwardly, with Apple's universal binaries. It is the only fixed-value field in the file.
42minor_versionAlmost always 0. The value 65535 has a specific meaning: the class uses preview features and will only load on exactly the JDK that compiled it, which is the real explanation behind a preview-feature class failing on a matching major version.
62major_versionThe class file version, and the field behind every UnsupportedClassVersionError. Since Java 5 it is the feature release plus 44 — Java 8 is 52, Java 17 is 61, Java 21 is 65 — and these two bytes are what a runtime compares against its own maximum before reading anything else.
82constant_pool_countOne more than the number of pool entries, because the pool is indexed from 1 and index 0 is reserved. A small utility class runs to a few dozen; a large framework class can approach the 65535 ceiling, which is a real limit generated code sometimes hits.
10variableconstant_poolEntries back to back, each opening with a one-byte tag that fixes its length: tag 1 is a UTF-8 string with a two-byte length prefix, tag 7 a class reference, tag 10 a method reference, tag 8 a string. Tags 5 and 6 (long and double) each consume two index slots — a rule that has broken more hand-written parsers than any other part of the format.
variable2access_flagsFirst field after the pool. 0x0001 public, 0x0010 final, 0x0200 interface, 0x4000 enum, and 0x0020 (ACC_SUPER) set on essentially everything compiled since 1997 for legacy invokespecial semantics — a plain public class typically reads 0x0021.
variable2this_classIndex of the pool entry naming this type, in internal form with slashes rather than dots. It has to agree with the file's path inside the JAR, which is why renaming a .class file on disk produces a NoClassDefFoundError that names both spellings.
variable2super_classIndex of the superclass entry, normally java/lang/Object. It is 0 only for java/lang/Object itself, the single class in the world with no parent.
variable2interfaces_countHow many direct superinterfaces follow, each as a two-byte pool index. Then come fields, methods and class attributes, every one of them length-prefixed, so the file must be read sequentially from the pool onward — there is no table of contents.

Telling it apart from its neighbours

Easily confused withHow to tell
Mach-O (universal/fat)Both open CA FE BA BE. Read bytes 4-7: a class file has minor_version then major_version, and major_version is at least 45 (Java 1.1) and currently in the sixties or seventies, while a universal binary has nfat_arch there — a small architecture count whose high half is zero. A nonzero value in bytes 6-7 above 44 means class file.
Java JARA JAR does not contain a class file at offset 0; it is a ZIP that begins 50 4B 03 04 and holds compressed class files inside. Seeing CA FE BA BE inside a JAR's bytes is expected — it just is not at the front, and the entry names in the central directory are what identify the archive.
Android DEXAndroid tooling compiles .class files and then throws them away: d8 merges them into a DEX file, which begins 'dex' and a newline and uses a register-based instruction set rather than the JVM's stack machine. An APK therefore contains no .class entries at all, which is the quickest way to tell an APK apart from a JAR that happens to target Android.
Java source (.java)Stated because build directories mix them: a .java file is plain text and a .class file starts with a byte that is not valid UTF-8 text. Any tool that opens a .class and shows readable class and method names is reading UTF-8 constant-pool entries, not source.

How these files break

  • A major_version newer than the runtime. Not corruption at all, but it is what people are usually looking at: the JVM reads bytes 6-7, sees a version above its maximum, and throws UnsupportedClassVersionError before parsing anything else. Compiling with release 21 and running on Java 17 produces exactly this.
  • Truncation. Because everything after the constant pool is length-prefixed and sequential, a class file cut short fails with ClassFormatError at whatever structure it was in the middle of, and the message rarely points at the real cause. The file being short is easier to see than the message.
  • A byte edited inside the constant pool. Changing a string literal to a different length without fixing its two-byte length prefix desynchronises every subsequent entry, so the parser reads a tag from the middle of a name and reports an unknown constant tag. This is why patching class files needs a library rather than a hex editor.
  • Text-mode transfer. The old FTP problem still reaches class files inside legacy build pipelines: CR LF translation shifts everything after the first occurrence, and because the constant pool is a stream of length-prefixed entries, the failure is a nonsense tag rather than a clean magic mismatch.

Where the format stands today

The class file is the JVM's actual interface: Java, Kotlin, Scala, Groovy and Clojure all compile to it, which is what makes them one ecosystem rather than five, and the format's stability is why a library compiled in 2005 still links against code compiled today. It is rarely handled on its own — classes travel inside JARs, WARs, module images and container layers — but it is what every bytecode tool, obfuscator, coverage agent and framework that generates proxies at runtime actually manipulates. Android is the notable exception: it consumes class files at build time and ships DEX instead. For a person with a hex editor, the useful property is that a class file is largely self-describing text: the constant pool spells out every class, method and field the type touches, so its dependencies are readable without decompiling anything.

Open Java class files on this site

Every one of these runs in your browser — the file never leaves your machine.

Related formats

Formats that are easy to confuse with Java class file — compare their leading bytes.

FormatFirst bytesExtension
Java JAR50 4B 03 04.jar
Mach-O (universal/fat)CA FE BA BE.dylib
Android DEX64 65 78 0A.dex

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the Java class file format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.