This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.
When Java creates an object, it checks to see if the class to which the object belongs has been loaded into memory. If not, it loads the object using the fully qualified name of the class. After the class is loaded and initialized, the object is created.
Let’s assume we’re using the class for the first time, so new objects can be divided into two processes: loading and initializing the class and creating the object.
Class loading process (first use of class)
Java uses the parent delegate model for class loading, so before describing the class loading process, let’s take a look at how it works:
The working process of the parental delegation model is as follows: If a ClassLoader receives a classload request, it first does not attempt to load the class itself. Instead, it delegates the request to the parent ClassLoader. This is true at every level of classloaders, so all load requests should eventually be sent to the top level of the launcher. Only when the parent class loader reports that it cannot complete the load request (it did not find the required class in its search scope) will the child loader attempt to load it itself.
The advantage of using the parent delegate mechanism is that the global uniqueness of a class is effectively guaranteed. When multiple classes with the same qualified name appear in the program, the class loader will always load only one of them.
1, load,
The classloader is responsible for reading the binary byte stream of a Class based on its fully qualified name into the JVM, storing it in the method section of the runtime memory area, and then converting it into an instance of a Java.lang.class object corresponding to the target type
2, validation,
** Format validation: ** Verifies compliance with class file specifications
** Semantic validation: ** Checks whether a type marked final contains subclasses; Check whether final methods ina class are overridden by subclasses. Make sure there are no incompatible method declarations between the parent and subclasses (for example, the method signature is the same but the method return value is different)
Operational validation: * * * * in the operand stack data must be correct operation, the constant pool of various symbols refer to perform validation (usually enforced in the parsing stage, check whether can be referenced by symbols described in the fully qualified name of positioning to the specified type, as well as a class member information access modifier whether to allow access, etc.)
3, preparation,
Allocates memory for all static variables in the class and sets an initial value for them (since no objects have been generated, instance variables are not part of this operation)
Static variables (constants) modified by final are assigned directly;
4, parsing,
Converting a symbolic reference in a constant pool to a direct reference (getting an in-memory pointer or offset to a class or field or method so that the method can be called directly) can be done after initialization. Resolve content that requires static binding. // All methods and fields that cannot be overridden are statically bound
Phases 2, 3, and 4 are also known as the linking phase, which incorporates the class data information from the binary byte stream loaded into the JVM into the JVM’s runtime state.
5. Initialization (parent after child)
-
4.1 Assigning values to static variables
-
4.2 Executing the Static Code Block
Note: Static code blocks can only be called by the JVM
Because a subclass has a dependency on its parent class, the class is loaded first and then the subclass is loaded, as is initialization. However, when the parent class initializes, the value of the static variable of the subclass is also present, which is the default value.
In the end, the method of area are stored the kinds of information, including static variables of a class, class initialization code (the assignment statements when static variables and static initialization code block), instance variable definitions, instance initialization code (instance variables of assignment statements example code block and structural method) and instance methods, and reference the class information of the parent.
Create an object
Allocate the memory required by the object in the heap
The allocated memory includes all instance variables of the class and its parent, but not any static variables
2. Assign defaults to all instance variables
Copy the definition of instance variables in the method area to the heap and assign default values
Execute the instance initialization code
The initialization sequence is to initialize the parent class and then the child class, executing the instance code block and then the constructor
4, If there is a c reference of the form Child C = new Child(), define Child on the stack to reference variable C, and then assign the address of the heap object to it
Note that each subclass object holds a reference to the superclass object, which can be called internally with the super keyword, but is not accessible externally
Supplement:
When invoking an instance method through an instance reference, first look for the actual type information of the object in the method area, and then look for the parent type information.
If the inheritance level is deep and the method to be called is in the parent class higher up, the call is inefficient because each call requires many lookups. In this case, most systems use a method called virtual method table to optimize the efficiency of calls.
The so-called virtual method table is to create a table for each class when the class is loaded. This table includes all dynamically bound methods of the object of the class and their addresses, including the methods of the parent class. However, a method has only one record, and only the subclass will retain the subclass after overwriting the parent class method. When you dynamically bind methods through objects, you only need to look up the table instead of looking up each parent class.