Class life cycle

1. Loading

Load classes through the loader. During loading, the loader does three things:

  1. Gets the binary byte stream defined by the fully qualified name of a class.
  2. Transform the static storage structure represented by this byte stream into the runtime data structure of the method area.
  3. Generate a java.lang.Class object representing this Class in the Java heap as an access point to the method area data.

2. Verification

Ensure that the classes being loaded are correct. There are four main points to check (an example from Understanding the Java Virtual Machine) :

1) File format verification:

Verify that the class file conforms to the specification to ensure that the byte stream is properly parsed and stored in the method area for subsequent validations in the method area. Such as:

  • Does it start with the magic number 0xCAFEBABE
  • Check whether the major and minor versions are within the processing range of the current VM.
  • If there are unsupported constant types in the constant pool (check the constant tag flag).
  • Is there any index value that points to a constant that does not exist or that does not conform to a type?
  • CONSTANT_Utf8_info whether there is data in the constant that does not conform to UTF8 encoding.
  • Whether any other information has been deleted or added to parts of the Class file and the file itself.

2) Metadata verification:

Verify that the semantics of metadata information conform to Java language specifications. Such as:

  • Does this class have a parent (except java.lang.object)
  • Does this class inherit from classes that are not allowed to inherit (such as classes modified by final)?
  • If the class is not abstract, does it implement all the methods required by its parent or interface?
  • Whether a field or method ina class conflicts with the parent class (for example, overwriting a final field in the parent class, or an invalid method overload)

3) Bytecode verification:

Verify semantic validity and logicality. Such as:

  • Ensure that the data types of the operand stack and the sequence of instruction codes work together at any time. For example, there is no such thing as putting an int on the stack and loading it into the local table as long.
  • Ensure that jump instructions do not jump to bytecode instructions outside the method body.
  • Ensure that type conversions in the method body are valid. For example, it is dangerous and illegal to assign a parent object to a subclass datatype, or even to a completely unrelated datatype that has no inheritance relationship.

4) Symbol drainage verification:

Verify that references outside the class are correct. Such as:

  • Whether a class can be found for a fully qualified name described by a string in a symbol reference.
  • Whether a field descriptor that matches a method exists in the specified class and the methods and fields described by the simple name.
  • The accessibility of classes, fields, and methods in symbolic references (private, protected, public, default) is accessible to the current class.

3. Preparation

Allocates memory for static variables of the class and initializes them to default values (assignment of specific values occurs during initialization). If the variable is both static and final, the stage assigns the value directly to the class’s constant pool.

4. Resolution

Converts symbolic references in a class to direct references. These include:

  1. Class or interface resolution
  2. Field analytical
  3. Class method resolution
  4. Interface method parsing

5. Initialization

Initialize the fields, code blocks, and constructors of the class. The order is as follows:

  1. Superclass static variable
  2. Superclass static code block
  3. Subclass static variable
  4. Subclass static code block
  5. The parent class is a non-static variable
  6. Superclass non-static code block
  7. Parent class constructor
  8. Subclasses are non-static variables
  9. Subclasses are non-static code blocks
  10. Subclass constructor

6, Using

2, Unloading is a class.

loader

Used to implement the loading action of the class. When two classes are loaded by different loaders, they must not be equal. Image:

Loaders have the following types:

1. Start the Bootstrap ClassLoader

The library responsible for loading is loaded into the vm memory in the path specified by the -xbootCLASspath parameter in the

\lib directory. This class loader is implemented in C++ and is part of the virtual machine. Other loaders are implemented in Java and inherit from the abstract java.lang.ClassLoader, independent of the virtual machine.

2. Extension ClassLoader

Sun.misc.Launcher$ExtClassLoader is used to load all class libraries in the path specified by the java.ext.dirs system variable in the <JAVA_HOME>\lib\ext directory.

3. Application ClassLoader

It is implemented by sun.misc.Launcher$AppClassLoader, which loads the library specified by the user’s ClassPath.

4. Custom User ClassLoader

A class loader customized by the developer.

Loader features:

1. Parental entrustment

When a class is loaded, it is checked to see if the parent class loader has loaded the class.

2, responsible for dependence

When a class is loaded, if it depends on other classes, the loader loads those classes as well.

3. Cache loading

Once a class is loaded, it is placed in the cache to avoid repeated loading.

Class loading timing

  1. Initialize the main class when the virtual machine starts.
  2. When new a class.
  3. When a static method is called and a static field is accessed, the class of which it belongs is initialized.
  4. When a subclass is initialized, the parent class is also initialized.
  5. If an interface defines the default method, initialization of the interface is triggered when classes that directly or indirectly implement the interface are initialized.
  6. Initializes a class when a reflection call is made to it using the reflection API.
  7. When you first call a MethodHandle instance, you initialize the class to which the method points.

A case where the class is not initialized (and may be loaded)

  1. By subclass referencing a static field of the parent class, the parent class is initialized but the subclass is not.
  2. Class initialization is not triggered when an array of objects is defined.
  3. When a constant is called. Because constants are stored in the constant pool of the calling class at compile time, there is no direct reference to the class, so initialization is not triggered.
  4. When you get a Class object by its Class name. For example, when Hello.Class, the Hello Class is not initialized.
  5. When loading a specified Class through class.forname, Class initialization is not triggered if initialize is false. The default is true when not set.
  6. With the default loadClass method of ClassLoader, initialization is not triggered (loaded, but not initialized).

The resources

  1. Geek time’s Advanced Java training camp for Teacher Qin
  2. In-depth Understanding of the Java Virtual Machine