preface

Project in the local running code times wrong today: Java. Lang. NoClassDefFoundError: Could not initialize class. This is a refresher on Java class loading order and object instantiation order. In the meantime, the purpose of this blog post is to take notes and summarize what you have learned. If you want to get something different from this post, you will be disappointed.

Analysis of the

  • Cause: NoClassDefFoundError This error occurs because the Java virtual machine can find the appropriate class at compile time, but the class loader cannot find the appropriate class at run time. One of the reasons is that the Java virtual machine throws a NoClassDefFoundError error when the class is unavailable at runtime when we want to call a method or access a static member of that class.
  • Compile-time and run-time: JAVA is a compiled language, and compilation is compiling the code you write into bytecode that the JAVA virtual machine can execute. Java code is designed to be easy to program, and Java virtual machines can’t execute Java code directly, so you compile the Java code, that is, generate.class files, and then the Java virtual machine runs the bytecode files, and the result is your program. Run is when the Java virtual machine runs the code you wrote (the compiled bytecode class file) and displays the results. Some classes pass at compile time but are thrown with an error at run time.
  • Solution:The class where the error occurs defines a static variable:
    • public static Map<Object, String> errorCodeMap;
    • This static variable is used without initialization, so it is resolved by adding a line of code:
      • if (errorCodeMap == null) errorCodeMapXGDX = new HashMap<>();

Instantiation of a Java object

  • The instantiation process of an object is divided into two parts: the loading initialization of a class and the initialization of an object, corresponding to the loading sequence of a class and the instantiation sequence of an object. The clinit method is used for class initialization and the init method is used for object instantiation

Java class loading order

  • The full life cycle of a class:

As you can see from the figure above, the life cycle of a class consists of seven major processes: load, validate, prepare, parse, initialize, use, and unload. All of these procedures operate on class files generated after JAVA code is compiled. The declaration cycle of a class is when the class file of a class is loaded into memory until it is unloaded.

  • Loading:

“Loading” is a phase of the “class loading” process, in which a virtual machine does three things:

1. Get the binary byte stream of a class based on its fully qualified name

2. Transform the static storage structure of this class into the runtime data structure of the method area

3. Generate a java.lang.Class object for this Class in the method area as the entry point for the method area to access this Class

Since the virtual machine does not specify how to fetch the binary stream, this phase is flexible for the user, such as reading binaries from zip packages or from the network, or even generating them at run time using dynamic proxy technology. The loading of ordinary classes is different from the loading of array classes. Array classes are created directly by the Java virtual machine instead of being loaded by the class loader, but array types are loaded by the class loader.

  • validation

The purpose of validation is to ensure that the contents of the class file are binary byte streams that conform to the virtual machine specification and prevent the virtual machine from crashing by executing some unsafe binary byte streams. Java virtual machine not only execute the Java language compiled class files, it can perform all binary byte stream file (as long as meet the file specification), so we cannot guarantee that other documents is legal, so you need to do some safety check, to ensure that the virtual machine code will not endanger the safety of the virtual machine itself.

The verification stage can be divided into four parts: file format verification, metadata verification, bytecode verification and symbol reference verification.

  • To prepare

The preparation phase is the phase that validates the allocation of memory for class variables and sets the initialization value, which is usually the default zero value for the data type. The memory used by these variables is allocated in the method area. The data initialized at this stage is only static fields and is assigned to initialized values (except for final modified fields), not values defined in the code. Note for memory allocation includes only the class variables, namely is decorated static variables, a class in Java variable has two kinds, one kind is is decorated static class variables, is an instance variable, from the understanding, class is equivalent to the template, the object is generated from the template instance, so the static variables in level belongs to class, Instead of instance variables. Any memory used by class variables should be allocated in the method area.

Java basic data type initial value:

  • parsing

The parsing phase is the process by which the VIRTUAL machine converts symbolic references to direct references. Symbolic references exist in class files in the format of “CONSTANT_Class_info”, “CONSTANT_Fieldref_info”, and “CONSTANT_Methodref_info”. The parse action is mainly for class or interface, field, class method, interface method, method type, method handle, and call qualifier class symbol references.

  • Initialize the

The initialization phase is the last step in the class loading process, and it is this phase that actually executes the user-defined Java program. In the preparation phase, variables have already been assigned their required initial values, while in the initialization phase, class variables (non-final modified class variables) and other variables need to be assigned, essentially executing the class’s < clinit >() method. The < clinit >() method is automatically generated after compilation. Unlike the class constructor, which does not require a user-displayed call, the virtual machine guarantees that the < clinit >() method of the parent class is executed before the < clinit >() method of the subclass, and the < clinit >() method of java.lang.object is executed first.

For the initialization phase, the virtual machine strictly specifies five cases in which classes must be initialized (classes are initialized only if they are actively used) : When encountering four direct code instructions — new, getStatic, putstatic, or Invokestatic — such as new a class, reading a static field (not modified by final), or calling a static method of a class, The following rules are also conditions that trigger class loading:

  • Classes are initialized when the JVM executes the new instruction. That is, when a program creates an instance object of a class.
  • The class is initialized when the JVM executes the getStatic directive. That is, the program accesses static variables of the class (not static constants, which are loaded into the runtime constant pool).
  • The class is initialized when the JVM executes the putStatic directive. That is, a program assigns a value to a static variable of a class.
  • The class is initialized when the JVM executes the InvokeStatic instruction. That is, a program calls a static method of a class.

The second:

  • A reflection call to a class using the methods of the java.lang. Refect package needs to trigger initialization if the class has not already been initialized.

The third:

  • When initializing a class, if the parent class is not initialized, the initialization of the parent class must be triggered first.

Fourth:

  • When a VM starts, the user needs to specify a primary class to execute. The VM will execute the primary class first.

Fifth:

  • When using JDK1.5 support, if a Java langl. Incoke. The final analytical results REF_getStatic MethodHandle instance, REF_putStatic, REF_invokeStatic method handles, If the class to which the method handle corresponds has not been initialized, it needs to be initialized first.
  • uninstall

Unload a Class when its Class objects are GC. In JVM life cycle classes, classes loaded by the JVM’s native classloader are not unloaded. But classes loaded by custom class loaders can be unloaded. The BootstrapClassLoader, ExtClassLoader, and AppClassLoader are responsible for loading classes provided by the JDK, so they are definitely not recycled. Instances of our custom class loaders can be reclaimed, so classes loaded using our custom loaders can be unloaded.

Object initialization order

(1) Initialize the final static property of the parent class and the subclass. (2) initialize the static property of the parent class and execute the static code block of the parent class. (3) Initialize the static property of the subclass and execute the static code block of the subclass (4) non-static properties of the parent class, non-static code block execution of the parent class, constructor execution of the parent class (5) Non-static properties of the child class, non-static code block execution of the child class, constructor execution of the child class

In short: superclass before subclass, static before constant before construction, code in the same hierarchy is executed in order. When a member variable in static and non-static code contains an object, the static code and constructors of that object’s class are also executed first

Parental delegation model

The class loading action of “get the binary stream that defines a class by the fully qualified name of a class” is implemented outside the virtual machine so that the application can decide how to get the required class. The code module that implements this action is called the class loader.

For any class, its uniqueness in the Java virtual machine needs to be determined by the class loader that loads it and by the class itself. Each class loader has a separate class namespace

  • Class loaders are provided by the following three systems:

(1) start class loader: the top-level loading class, implemented by C++, is responsible for loading jar packages and classes in %JAVA_HOME%/lib or all classes in the path specified by the -xbootclasspath parameter.

(2) Extension class loader: mainly responsible for loading jar packages and classes under the directory %JRE_HOME%/lib/ext, or jar packages under the path specified by the java.ext.dirs system variable.

(3) Application class loader: responsible for loading the user’s ClassPath code

  • The parent delegation model works like this: if a class loader receives a request for a class load, it first does not attempt to load the class itself, but delegates the request to the parent class loader. This is true for every classloader, and only if the parent cannot find the specified class in its search scope (that is, ClassNotFoundException) will the child loader attempt to load it itself.

  • Benefits:

  • The advantage of using the parent delegate model is that Java classes have a hierarchy of priorities along with their classloaders. For example, the java.lang.Object class, which resides in rt.jar, is delegated to the Bootstrap ClassLoader at the top of the model by any ClassLoader. Therefore, the Object class is the same class in each ClassLoader environment of the program. On the other hand, if there were no parent delegate model and each class loader loaded it by itself, if the user wrote a java.lang.Object class of the same name and put it in the ClassPath, the system would have multiple Object classes and the program would be confused. So, if a developer tries to write a Java class with the same name as one in the Rt.jar library, it will compile fine, but it will never be loaded and run.
  • Improves the security of software systems by making it impossible for user-defined class loaders to load reliable classes that should be loaded by their parent class loaders

conclusion

If an object wants to be instantiated, it has to be initialized by the loading of the class and then the initialization of the object. I didn’t understand the connection between class loading and object initialization until today. For details, see this article, which is well written: Basics: Detailed JAVA object instantiation process

reference

  • Deep Understanding of Virtual Machines
  • JavaGuide