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-
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.
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. - A
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-
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.1 | 45 | 45 |
1.2 | 46 | 45 to 46 |
1.3 | 47 | 45 to 47 |
1.4 | 48 | 45 to 48 |
5 | 49 | 45 to 49 |
6 | 50 | 45 to 50 |
7 | 51 | 45 to 51 |
8 | 52 | 45 to 52 |
9 | 53 | 45 to 53 |
10 | 54 | 45 to 54 |
11 | 55 | 45 to 55 |
12 | 56 | 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 theclass
file format, so JDK 12 supported minor versions of 0 and 65535 under major version 56. Subsequent JDKs introduce support forN
.0 andN
.65535 whereN
is the corresponding major version of the implemented Java SE Platform.
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 Name | Value | Interpretation |
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_FINAL | 0x0010 | Declared final; no subclasses allowed. |
ACC_SUPER | 0x0020 | Treat superclass methods especially when invoked by the invoke special instruction. |
ACC_INTERFACE | 0x0200 | Is an interface, not a class. |
ACC_ABSTRACT | 0x0400 | Declared abstract; must not be instantiated. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |
ACC_ENUM | 0x4000 | Declared as an enum type. |
ACC_MODULE | 0x8000 | Is 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.
You can download the full source code of this example here: Java .class File Example