Running a Java program

Remember the beginning of learning Java, the first thing to learn is how to write Java code in a text editor, and then compile and run.

  1. Create a new hello.java file, open it with Notepad, write the following code and save it.
public class Hello {
    public static void main(String[] args) {
        System.out.println("hello java"); }}Copy the code
  1. Open the console, positioning to Hello. The Java file directory CD/Users/stardust/Desktop/TestCode
  2. Run the javac -d hello. Java command to compile the file
  3. Use the Java Hello command to print Hello Java in the console

This is probably the first time. Why is it possible to run the code this way, and what is the mechanism behind it? Now let’s find out.

Class loading process

When we use a Java command to run a class’s main method launcher, we first start a JVM container and load the class’s bytecode files into the JVM.

Java’s underlying layer is actually implemented by C++, so when we type a Java command, the underlying jvm.dll is called to create the Java core virtual machine (JVM), followed by a root (boot) classloader instance. The bootloader loads the SUN.misc.Launcher class in the JDK and calls its getLauncher() method to get a Launcher instance. You can get an AppClassLoader instance from the Launcher instance. Load Hello.class via AppClassLoader. After loading, the JVM executes the main method of the class. When the program ends, the JVM destroys itself. As shown below:

Note that:

  • The Launcher class implements the hunky-dandy singleton pattern, so there is only one instance of the Launcher per JVM.
  • Sun.misc.Launcher#getClassLoader returns an instance of AppClassLoader, The Launcher class there is sun. Misc. The Launcher. AppClassLoader and sun. Misc. The Launcher. ExtClassLoader two loaders, the logic on the father-son relationship, But ExtClassLoader is not a parent of AppClassLoader. In fact, both class loaders inherit from java.net.URLClassLoader

LoadClass The step of loading a class

When a program actively uses a class, if the class has not been loaded into memory, the system will initialize the class through three steps: load, connect, and initialize. If there are no exceptions, the JVM will complete all three steps in succession, so these steps are sometimes referred to collectively as class loading or class initialization.

Class loading

Class loading refers to reading a class’s class file into memory and creating a java.lang. class object for it. That is, when any class is used in a program, the system creates a java.lang. class object for it.

The loading of classes is done by classloaders, which are usually provided by the JVM and are the basis on which all previous programs are run. These classloaders provided by the JVM are often referred to as system classloaders. In addition, developers can create their own classloaders by inheriting the ClassLoader base class.

By using different class loaders, you can load the binary data of a class from different sources, usually the following.

  • Load a class file from the local file system, which is how most of the previous sample programs load classes.
  • It is also common to load a class file from a JAR package. The database driver classes used in JDBC programming are in the JAR file, and the JVM can load the class file directly from the JAR file.
  • Load class files over the network.
  • Dynamically compile and load a Java source file. Classloaders generally do not have to wait for “first use” of a class before loading it, and the Java Virtual Machine specification allows the system to preload certain classes.

Connection of a class

When the Class is loaded, a corresponding Class object is generated for it and the connection phase is entered, which merges the binary data of the Class into the JRE. Class join can be divided into the following three stages.

  • (1) Verification: The verification stage is used to check whether the loaded class has the correct internal structure and is consistent with other classes.
  • (2) Preparation: The class preparation stage is responsible for allocating memory for the static Field of the class and setting the default initial value.
  • (3) Parsing: Replace symbolic references in the binary data of the class with direct references.

Class initialization

During the initialization phase of the class, the virtual machine is responsible for initializing the class, primarily the static Field. There are two ways to specify an initial value for a static Field in a Java class. ② Use a static initialization block to specify an initial value for a static Field.

The JVM initializes a class in the following steps.

  • (1) If the class has not been loaded and connected, the program loads and connects the class first.
  • (2) If the immediate parent of the class has not been initialized, initialize its immediate parent first.
  • (3) If there are initialization statements in the class, the system will execute these initialization statements in turn.

When performing step 2, the system initializes the immediate parent class by following steps 1 to 3. If the immediate parent has an immediate parent, the system repeats the three steps to initialize the parent first… And so on, so the JVM always initializes the java.lang.Object class first. When a program actively uses any class, the system guarantees that the class and all its parents (both direct and indirect) are initialized.