This question is often asked when interviewing Java engineers.

After reading this article carefully, just can do have a good idea, interview chat.


1. Introduction to the JVM (Brief Introduction)

JVM full name is Java Virtual Machine, Java Virtual Machine, which is another Virtual computer on the computer, this is not the same as we use VMWare, that Virtual thing you can see, this JVM you can not see, it exists in memory. We know that the basic structure of a computer is: Arithmetic unit, controller, memory, input and output devices, and that the JVM is also have the complete set of elements, the arithmetic unit is, of course, is to hardware CPU processing, also just in order to adapt to “compile once, run anywhere”, you need to do a translation action, and then the JVM with your own command set, this and similar to the command set assembly, Each assembly command set is specific to a family of cpus. For example, the 8086 series can run on the 8088, but not on the 8051, while the JVM’s command set can run anywhere because the JVM does the translation, depending on the CPU, into different machine languages.

The most important thing we need to understand in the JVM is the storage part of it. Storage? The hard disk? NO, NO, the JVM is an in-memory virtual machine, so its storage is memory. All the classes, constants, variables, and methods we write are in memory. This determines how robust and efficient our programs run.

2. JVM Composition (Read carefully)

This diagram is based on the JVM configuration diagram that is widely available on the Internet. If you look at this diagram, the entire JVM is divided into four parts:

Class Loader Class Loader

Class loader is used to load a class file into memory. For example, write a helloword. Java program and compile it into a class file using javac. The JVM Specification defines the structure of a Class file. The JVM Specification defines the structure of a Class file.

ClassFile {
      u4 magic;
      u2 minor_version;
       u2 major_version;
      u2 constant_pool_count;
      cp_info constant_pool[constant_pool_count-1];
      u2 access_flags;
      u2 this_class;
      u2 super_class;
      u2 interfaces_count;
      u2 interfaces[interfaces_count];
      u2 fields_count;
      field_info fields[fields_count];
      u2 methods_count;
      method_info methods[methods_count];
      u2 attributes_count;
      attribute_info attributes[attributes_count];
    }
Copy the code

For more details, read chapter 4 of The JVM Specification, “The Class File Format,” which is not covered here.

The Execution Engine is responsible for the Execution of the Class Loader. The Execution Engine is responsible for the Execution of the Class Loader.

Execution Engine

The execution engine, also called an Interpreter, interprets commands and submits them to the operating system for execution.

Native Interface Indicates the local Interface

The function of the local interface is to fuse different programming languages for Java, its original purpose is to fuse C/C++ programs, Java was born when C/C++ prevail, to get a foothold, there must be a smart, wise call C/C++ programs, Therefore, a special area of memory is created to process the code marked as Native by registering native methods in the Stack and loading native Libraies during Execution of the Execution Engine. At present, this method is used less and less, except for hardware-related applications, such as Java program to drive printers, or Java system to manage production equipment, has been relatively rare in enterprise applications, because the communication between heterogeneous fields is very developed, such as Socket communication, You can also use Web Services and so on without going into details.

Runtime data area Indicates the running data area

The running data area is the focus of the entire JVM. Everything we write is loaded here before it runs, and the Java ecosystem thrives because of the region’s autonomy.

The entire JVM framework is loaded by the loader, which processes the data in memory, interacts with heterogeneous systems via a local interface, and voyea-a complete system is born!

How does the JVM load class files?

All classes in Java need to be loaded into the JVM by the class loader to run. The class loader is itself a class, and its job is to read the class file from the hard disk into memory. When writing programs, we hardly need to care about class loading because it is implicitly loaded, unless we have special uses, such as reflection, that require explicit loading of the required class.

There are two types of class loading

1. Implicit loading. When the program encounters an object generated through new or other methods during the running process, it implicitly calls the class loader to load the corresponding class into the JVM

2. Explicitly load the required classes using methods such as class.forname()

The difference between implicit and explicit loading: Are they the same? Java classes are loaded dynamically. Instead of loading all classes at once and then running them, the underlying classes (like the base classes) that the program runs on are fully loaded into the JVM, and other classes are loaded as needed. This, of course, is to save memory overhead.

Java has three class loaders

There are three types of Java:

1. The system class

2. The extension class

3. Classes that are customized by programmers

The Bootstrap Loader is responsible for loading system classes (i.e. built-in classes such as String, Corresponding to the System in C # classes and class in the C/C + + standard library) | - ExtClassLoader / / is responsible for loading extension classes (that is, a derived class and implementation class) | - AppClassLoader / / is responsible for loading application class (programmer custom class)Copy the code

Each of the three loaders does its job, but how do they work together? Which class should be done by which classloader? To solve this problem, Java employs the delegation model mechanism.

The delegate model mechanism is simple: when a class loader needs to load a class, it asks its Parent to load it in its search path, and if it can’t find it, it searches for the class in its own search path. This order is essentially a top-down search at the loader level, because the loader must ensure that the underlying classes are loaded. There is also a security consideration for this mechanism: if someone loads a malicious underlying class into the JVM, the delegate model mechanism will search for its parent class loader, which is obviously impossible to find, and will not load it in.

We can get the classloader with code like this:

ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();
Copy the code

One important thing to note is that Java logically does not have an entity for BootstrapKLoader! Because it is written in C++, printing its contents will result in null.

The previous is a simple introduction to the class loader, its principle mechanism is very simple, is the following steps:

1. Load: find and import class files;

2. The connection:

(1) Check: check the correctness of the loaded class file data; (2) Preparation: allocate storage space for static variables of the class; (3) Parse: Convert symbolic references to direct references (this step is optional)Copy the code

3. Initialization: Initialize static variables, static code blocks.

This process starts when a program calls a static member of the class, so the static method main() becomes the entry method of a normal program. Class constructor also raises this action.


Let’s talk a little bit more about the loading process

loading

The JVM loads the compiled. Class binaries into memory before the Java program is run for subsequent use by the provider, using the ClassLoader. Parts of the load phase and the connect phase (such as some bytecode file format validation actions) intersect, and the connect phase may begin before the load phase ends. However, actions that occur during the load phase are still part of the connection phase.

The connection

  • Connection-authentication

    Validation is the first step in connection to ensure that the byte stream of the Class file contains information that meets the requirements of the current virtual machine and does not compromise the security of the virtual machine itself. The four steps of the verification stage: file format verification, metadata verification, bytecode verification, symbol reference verification.

File format verification: Verifies that the byte stream complies with the Class file format specification and can be processed by the current version of the VM. Metadata validation: Semantic analysis of the information described by bytecode to ensure that the content described conforms to the Requirements of the Java language specification. Bytecode verification: Through data flow and control flow analysis to determine that program semantics are legitimate and logical. Symbolic reference checking: Symbolic reference checking can be thought of as checking the compatibility of information outside the class itself (various symbolic references in the constant pool).Copy the code
  • Connect – Ready

    This phase formally allocates memory for class variables and sets their initial values. The memory used by these variables is allocated in the method area. Only class variables are allocated, not instance variables (which will be allocated in the Java heap along with the object when it is instantiated). In addition, the static class variable assigned here is defined with its default value. Because no Java methods are executed at this stage, the correct assignment will be performed at the initialization stage.

  • Connection-parsing

    This phase is the process by which the virtual machine replaces symbolic references in the constant pool with direct references.

Initialize the

This is the final step in class loading and actually executes the bytecode defined in the class, which is the.class file. The initialization phase is the process of executing the class constructor methods and actually initializing class variables and other resources.