Core Java

Java .class File Example

In this post, we feature a comprehensive article on Java .class File.

Have you ever wondered:

  • What is bytecode in Java?
  • What makes Java a platform-independent language?
  • What is the Java .class file?
  • Structure of Java class file.

In this article, we will address all the above questions and we will deep dive into understanding bytecode or .class file in Java world.

1. What is bytecode in Java?

Java bytecode is the result of the compilation of a Java program, an intermediate representation of that program which is machine-independent. Is machine-independent because of the Java virtual machine that runs the bytecode in proxy of the processor which means that a Java programmer does not have to be knowledgeable about the quirks and nuances about specific operating systems and processors that the program will be run on because the virtual machine takes care of those specifics? 

The Java bytecode gets processed by the Java virtual machine (JVM) instead of the processor. It is the job of the JVM to make the necessary resource calls to the processor to run the bytecode.

2. What makes Java a platform-independent language?

Yes, you guessed correctly. It is the .class file or Java Bytecode. Once you finish writing your java program and use the javac command to compile. It generates separate class files for each class present in the java source file. If you have multiple classes in one source file, Java compiler generates multiple class one file each class.

The .class file generated by Java Compiler contains JVM Specific instructions in the form of bytecode. It can only be understood by JVM. There are multiple flavors of JVM written for each of the platform(Mac, Android, Window) in many different JVM based language (Scala, Jikes, Espresso, etc). JVM can understand bytecode or interpret the .class file. JVM can process the instructions therein .class file which makes the code written and compiled in one platform can run in different platform. This is how Java is a platform-independent language.

Below is a typical Java program execution flow-

Java .class File - Java program Execution flow
Java program Execution flow

3. What is the Java .class file

It is now very much clear that .class file is a file which contains Java bytecode which is an intermediate code generated after compilation of source Java code. Class files have a .class extension and generated as per class basis meaning the separate class file is generated for all classes either in the same file or in different files. Class files are input for a JVM which will get interpreted by Just In Time Compiler to convert bytecode into machine code and execute it on Operating System to achieve functionality implemented in Java source code.

4. Class file Example

Let’s take a very simple example to print a message. We will have a MessageGenerator class having genetateMessage() which will take username as an argument and greet that user by returning “Hello <username>!” and if user name got passed as null it will return “Hello World!”. We will also have a driver class ClassFileDemo which will have main() to call genetateMessage() method of MessageGenerator class.

Create a file name it as ClassFileDemo.java and place below code into it.

ClassFileDemo.java

import java.util.Objects;

public class ClassFileDemo {
	public static void main(String[] args) {
		System.out.println(new MessageGenerator().generateMessage("Vipul"));
	}
}

class MessageGenerator {
	public String generateMessage(String username) {
		if (Objects.nonNull(username))
			return "Hello" + username + "!";
		else
			return "Hello world!";
	}
}

5. Compiling the source code

Open command prompt in windows or terminal in Mac OS and Linux and run the javac ClassFileDemo.java command to compile the source code. As soon as command finishes execution you could be able to see two .class files got generated with name ClassFileDemo.class and MessageGenerator.class for each respective class.

Now, we can execute java ClassFileDemo to run our program.

Java .class File - Compile and run java source code
Compile and run java source code

Explanation: As shown in the above figure Initially we are having one java file ClassfileDemo.java. We compiled it using javac command and it generated two files naming ClassfileDemo.class and MassageGenerator.class as explained in the previous section. Next, we run the class having main() i.e ClassFileDemo by using java command and got the output as “Hello Vipul!

6. Java Class file Structure

Now since we have enough background on class file. Let’s look at the structure and format of the class file in java.

  • Each class file contains the definition of a single class, interface, or module.
  • class file consists of a stream of 8-bit bytes (also called byte stream or bytecode).
  • Multibyte data items are always stored in big-endian order, where the high bytes come first.

The class file structure looks something like below.

ClassFile {
     4-byte         magic;
     2-byte         minor_version;
     2-byte         major_version;
     2-byte         constant_pool_count;
     cp_info        constant_pool[constant_pool_count-1];
     2-byte         access_flags;
     2-byte         this_class;
     2-byte         super_class;
     2-byte         interfaces_count;
     2-byte         interfaces[interfaces_count];
     2-byte         fields_count;
     field_info     fields[fields_count];
     2-byte         methods_count;
     method_info    methods[methods_count];
     2-byte         attributes_count;
     attribute_info attributes[attributes_count];
 }

Let’s take each part of ClassFile structure one by one

magic: The first 4 bytes of ClassFile are called as magic. It supplies the magic number which is used to identify class file format. It is a predefined hexadecimal value i.e 0xCAFEBABE. JVM uses it to identify whether the .class file is generated by a valid java compiler or not.

Let’s see what happens if JVM doesn’t find a valid magic_number at the beginning of the class file. We will create a file MagicNumberDemo.java having below code.

MagicNumberDemo.java

public class MagicNumberDemo{
    public static void main(String[] args) {
		System.out.println("Magic Number Demo");
	}
}

Compile this java code using javac MagicNumberDemo.java command.

Now open MagicNumberDemo.class file in any editor of your choice. You will see content like below. It may defer in your system based on the editor you are using.

Êþº¾   4 
          
       ()V Code LineNumberTable main ([Ljava/lang/String;)V 
 SourceFile MagicNumberDemo.java      Magic Number Demo    MagicNumberDemo java/lang/Object java/lang/System out Ljava/io/PrintStream; java/io/PrintStream println (Ljava/lang/String;)V !                        *· ±    
                     %      ² ¶ ±    
        
     

Let’s remove some character from the beginning and save it.

Now we will run our MagicNumberDemo class using java MagicNumberDemo command. It will give us a run time exception (See the highlighted text in below image): Incompatible magic value 4273651200 in class file MagicNumberDemo. for more details see the image below-

Java .class File - value error in java
magic value error in java

Note: This error may vary depending on how much information you remove the .class file.

minor_version & major_version: major_version and minor version are next 4-byte of information 2-byte each. These will be used as a class file version. To get the class file version use major_version.minor_version format.

Below is the table lists what class file version gets generated by a specific version of java compiler. And which version of the class file is supported by a specific version of JVM.

Java Version Corresponding major version Supported major versions
1.0.2 45 45
1.14545
1.24645 to 46
1.347 45 to 47
1.448 45 to 48
549 45 to 49
650 45 to 50
751 45 to 51
852 45 to 52
953 45 to 53
1054 45 to 54
1155 45 to 55
1256 45 to 56

For a class file whose major_version is 56 or above, the minor_version must be 0 or 65535.

For a class file whose major_version is between 45 and 55 inclusive, the minor_version may be any value.

A historical perspective on versions of the class file format is warranted. JDK 1.0.2 supported versions 45.0 through 45.3 inclusive. JDK 1.1 supported versions 45.0 through 45.65535 inclusive. When JDK 1.2 introduced support for major version 46, the only minor version supported under that major version was 0. Later JDKs continued the practice of introducing support for a new major version (47, 48, etc) but supporting only a minor version of 0 under the new major version. Finally, the introduction of preview features in Java SE 12 (see below) motivated a standard role for the minor version of the class file format, so JDK 12 supported minor versions of 0 and 65535 under major version 56. Subsequent JDKs introduce support for N.0 and N.65535 where N is the corresponding major version of the implemented Java SE Platform.

JavaSE Docs

constant_pool_count: Next 2-byte represents the string constant pool count whose value will be equal the number of records in the constant_pool table plus one.

constant_pool: this will be a variable length. It is a table of structures and represents various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures. The constant_pool table index varies from 1 to constant_pool_count – 1.

access_flags: next 2-byte information represents access modifier and denotes access permissions to and properties of this class or interface. a comprehensive list of access_flag their hexadecimal value and interpretation is given below-

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_FINAL0x0010Declared final; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods especially when invoked by the invoke special 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.
ACC_MODULE0x8000Is a module, not a class or interface.

this_class: next 2-byte information if for this_class. It 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: next 2-byte of information is as same as this_class but it represents a direct super_class structure if this_class. The ClassFile structure for super_class should not have its ACC_FINAL flag set in its access_flag list.
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.

interfaces_count: As the name suggests the next 2-bytes of information interfaces_count  represents the number of direct super interfaces of this class or interface type.

interface[]: It returns interfaces information implemented by the current class file. Each value in the interfaces array must be a valid index into the constant_pool table.

fields_count: this 2-byte represents the number of static variables present in the current class file or technically, the number of field_info structures in the fields table.

fields[]: It represents fields (static variable) information present in the current class file. It does not include items representing fields that are inherited from superclasses or super interfaces.

method_count: It represents the number of methods present in the current class file or the number of method_info structures in the methods table.

method[]: It returns information about all methods present in the current class file. Each value in the interfaces array must be a valid index into the constant_pool table.

attributes_count: this 2-byte of information represents the number of attributes (instance variables) present in the current class file or the number of attributes in the attributes table of this class.

attributes[]: It provides information about all attributes (instance variables) present in the current class file. Each value of the attributes table must be an attribute_info structure.

This leads to the end of the article. Hope you enjoyed it.

7. Download the Source Code

This was an example of the Java .class file.

Download
You can download the full source code of this example here: Java .class File Example

Vipul Kumar

Vipul is a Senior Software Engineer with experience in different software technologies including Java, Javascript, Angular, React, Material Design, databases (MySQL), HTML/CSS and even AWS, Big Data and Machine Learning. He likes learning new technologies and using the latest libraries in his work.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button