Today, let’s focus on the class file format, the hardware- and operating system-independent binary format used to represent compiled classes and interfaces.

A class file consists of a stream of 8-bit bytes. All 16-bit, 32-bit, and 64-bit quantities are constructed by reading in two, four, and eight consecutive 8-bit bytes, respectively.

A class file consists of a single ClassFile structure:

nametypecount
magicu41
minor_versionu21
major_versionu21
constant_pool_countu21
constant_poolcp_infoconstant_pool_count-1
access_flagsu21
this_classu21
interfaces_countu21
interfacesu2interfaces_count
fields_countu21
fieldsfield_infofields_count
methods_countu21
methodsmethod_infomethods_count
attributes_countu21
attributesattribute_infoattributes_count

To illustrate, I introduce this snippit of code for example.

package com.qiniu.fusion.app;

public class JavaTestApp {

    static String localName;
    public static void main(String[] args) {
        System.out.println("local name = " + localName);
    }
}

magic

The magic item supplies the magic number identifying the class file format; it has the value 0xCAFEBABE.

minor_version, major_version

The values of the minor_version and major_version items are the minor and major version numbers of this class file. Together, a major and a minor version number determine the version of the class file format. If a class file has major version number M and minor version number m, we denote the version of its class file format as M.m. Thus, class file format versions may be ordered lexicographically, for example, 1.5 < 2.0 < 2.1.

A Java Virtual Machine implementation can support a class file format of version v if and only if v lies in some contiguous range Mi.0 ≤ v ≤ Mj.m. The release level of the Java SE platform to which a Java Virtual Machine implementation conforms is responsible for determining the range.

Take the above for example, minor_version is 0x0000 and major_version is `0x0034, representing 50 in decimalism. So this class file can be executed by JDK1.8 or higher.

Output from javap supports the above argument .

constant

constant_pool_count

The value of the constant_pool_count item is equal to the number of entries in the constant_pool table plus one.

constant_pool[]

The constant_pool is a table of structures representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures.

The format of eachconstant_pool table entry is indicated by its first “tag” byte.

The value of constant_pool_count in this example is 0x0031, same as 49 in decimal base.

javap can also print the information of constant pool.

access_flags

The value of the access_flags item is a mask of flags used to denote access permissions to and properties of this class or interface. The interpretation of each flag, when set, is as shown in the following table:

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_FINAL0x0010Declared final; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE0x0200Is an interface, not a class.
ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation type.
ACC_ENUM0x4000Declared as an enum type.

The flag 0x0021 indicates that this class is ACC_PUBLIC and ACC_SUPER.

class and interface

this_class

The value of the this_class item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the class or interface defined by this class file.

super_class

For a class, the value of the super_class item either must be zero or must be a valid index into the constant_pool table. If the value of the super_class item is nonzero, the constant_pool entry at that index must be a CONSTANT_Class_infostructure representing the direct superclass of the class defined by this class file. Neither the direct superclass nor any of its superclasses may have the ACC_FINAL flag set in the access_flags item of its ClassFile structure.

If the value of the super_class item is zero, then this class file must represent the class Object, the only class or interface without a direct superclass.

For an interface, the value of the super_class item must always be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the class Object.

interfaces_count

The value of the interfaces_count item gives the number of direct superinterfaces of this class or interface type.

interfaces[]

Each value in the interfaces array must be a valid index into the constant_pool table. The constant_pool entry at each value of interfaces[*i*], where 0 ≤ i < interfaces_count, must be a CONSTANT_Class_info structure representing an interface that is a direct superinterface of this class or interface type, in the left-to-right order given in the source for the type.

this_class is 0x000a, super_class is 0x000b, both are corresponding to the output of javap.

interfaces_count is 0x0000, which means this class has no direct superinterfaces.

field

fields_count

The value of the fields_count item gives the number of field_info structures in the fields table. The field_info structures represent all fields, both class variables and instance variables, declared by this class or interface type.

fields[]

Each value in the fields table must be a field_info structure giving a complete description of a field in this class or interface. The fields table includes only those fields that are declared by this class or interface. It does not include items representing fields that are inherited from superclasses or superinterfaces.

field_info

Each field is described by a field_info structure

field_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

access_flags

The value of the access_flags item is a mask of flags used to denote access permission to and properties of this field. The interpretation of each flag, when set, is as shown,

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_PRIVATE0x0002Declared private; usable only within the defining class.
ACC_PROTECTED0x0004Declared protected; may be accessed within subclasses.
ACC_STATIC0x0008Declared static.
ACC_FINAL0x0010Declared final; never directly assigned to after object construction (JLS §17.5).
ACC_VOLATILE0x0040Declared volatile; cannot be cached.
ACC_TRANSIENT0x0080Declared transient; not written or read by a persistent object manager.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ENUM0x4000Declared as an element of an enum.

name_index

The value of the name_index item must be a valid index into the constant_pool table.

descriptor_index

The value of the descriptor_index item must be a valid index into the constant_pool table.

attributes_count

The value of the attributes_count item indicates the number of additional attributes of this field.

attributes[]

Each value of the attributes table must be an attribute structure. A field can have any number of attributes associated with it.

Back to the previous example, There is only 1 field in the class just likefields_count is 1.

Considering the structure of field_info, it’s easy to infer,

This variable is static with access_flags is 0x0008. The name_index 0x000c points to localName, name of the variable. The entry on index 0x000d, the value of descriptor_index is String, the type of this variable. The attributes_count is 0x0000 so this variable has no additional attributes.

method

methods_count

The value of the methods_count item gives the number of method_info structures in the methods table.

methods[]

Each value in the methods table must be a method_info structure giving a complete description of a method in this class or interface. If neither of the ACC_NATIVE and ACC_ABSTRACT flags are set in the access_flags item of a method_infostructure, the Java Virtual Machine instructions implementing the method are also supplied.

The method_info structures represent all methods declared by this class or interface type, including instance methods, class methods, instance initialization methods, and any class or interface initialization method . The methods table does not include items representing methods that are inherited from superclasses or superinterfaces.

method_info

Each method, including each instance initialization method and the class or interface initialization method, is described by a method_info structure.

method_info {
    u2             access_flags;
    u2             name_index;
    u2             descriptor_index;
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

access_flags

The value of the access_flags item is a mask of flags used to denote access permission to and properties of this method. The interpretation of each flag, when set, is as following.

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_PRIVATE0x0002Declared private; accessible only within the defining class.
ACC_PROTECTED0x0004Declared protected; may be accessed within subclasses.
ACC_STATIC0x0008Declared static.
ACC_FINAL0x0010Declared final; must not be overridden.
ACC_SYNCHRONIZED0x0020Declared synchronized; invocation is wrapped by a monitor use.
ACC_BRIDGE0x0040A bridge method, generated by the compiler.
ACC_VARARGS0x0080Declared with variable number of arguments.
ACC_NATIVE0x0100Declared native; implemented in a language other than Java.
ACC_ABSTRACT0x0400Declared abstract; no implementation is provided.
ACC_STRICT0x0800Declared strictfp; floating-point mode is FP-strict.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.

As to name_index, descriptor_index, attributes_count and attributes[] are the same as ones in field_info.

From the above snapshot, we can conclude methods_count is 0x0002. So we can find 2 methods in the class JavaTestApp. The first one’s index in constant pool is 0x0001, then we switch to javap.

The first method is init automatically added by javac. With access_flags 0x0001 meaning public, name_index 0x000e, descriptor_index 0x000f, it’s easy to locate them in constant pool.

The attributes_count of 0x0001 hints the init method has one attributes.

All attributes have the following general format:

attribute_info {
   u2 attribute_name_index;
   u4 attribute_length;
   u1 info[attribute_length];
}

The attribute_name_index is 0x0010, attribute_length is 0x002f.

Let’s go to 0x0010 directly, and find this attribute is Code.

A Code attribute contains the Java Virtual Machine instructions and auxiliary information for a single method, instance initialization method, or class or interface initialization method.

You can also see Code by javap.

attribute

attributes_count

The value of the attributes_count item gives the number of attributes in the attributes table of this class.

attributes[]

Each value of the attributes table must be an attribute_info structure.

The attributes defined by this specification as appearing in the attributes table of a ClassFile structure are the InnerClasses, EnclosingMethod, Synthetic , Signature , SourceFile , SourceDebugExtension, Deprecated , RuntimeVisibleAnnotations , RuntimeInvisibleAnnotations, and BootstrapMethods attributes.

Reference

The class File Format JVM Class 文件结构详解一