Junior Java back-end summer internship summary-JVM articles

img


The blogger is now in his junior year and is looking for a summer internship from March, and he is ready to go to tx for an internship in the summer! I have summarized a lot of real interview questions, and hope to help everyone who is looking for a job! Relevant references will be marked with links to the original text, respect the original!


table of Contents


reference:


1. jvm architecture

  1. Class loading subsystem
  2. Runtime data area
  3. Bytecode execution engine
  4. Native method interface
image-20210510235026459


image-20210510214219240


image-20200802154319450


First, the Java code is converted into bytecode through the ClassLoader, and then the bytecode is loaded into the memory in the Runtime Data Area, and the bytecode file is just a set of instruction set specifications of the JVM , And cannot be directly handed over to the underlying operating system for execution. Therefore, a specific command parser execution engine (Execution Engine) is required to translate bytecode into underlying system instructions and then handed over to the CPU for execution. In this process, other commands need to be called. The native interface of the language (Native Interface) realizes the function of the whole program.

image-20210510135256214


img

2. Class Loader

image-20210424175240303

Which ExtClassloaderis the system class loader, thread context loader

  • System class loader : Since the application class loader is getSystem-ClassLoader()the return value of the method in the ClassLoader class , it is also called " 系统类加载器" in some occasions . It is responsible for loading all the class libraries on the user class path (ClassPath), and developers can also use this class loader directly in the code.
  • Thread context loader : Through the above three loader, each loader can access it

If you want a custom loader, need to inherit java.lang.ClassLoaderthe class, and in order to meet the parents delegate mechanism, you need to specify the parent class loader for the expansion loader


3. Class loading process

Class Loader Class loader
image-20210316223145616
image-20210316222046713
  1. Load : Load the .Classbytecode file into the memory, create an java.lang.Classobject representing this class
  2. Link : link class, the class of binary code into Java Runtime Environment JREin
  3. Initialization : then hand over JVMto the initialization of the class

Detailed process diagram :

image-20210316223006506

4. What is the parent delegation mechanism

When a .class file to be loaded, without regard to our custom class loader class, will first AppClassLoaderin is loaded by checking if there would be no need to load; if not'll make a parent loader , then call the parent load 's loadClass method. The parent loader will also first check whether it has been loaded. If it does not go up, it will check whether it has been loaded until it arrives BootstrapClassLoader, and will not choose to load it by itself. When the root loader is reached, it will start to check whether the current class can be loaded, and it will end when it can load, and the current loader will be used; otherwise, the child loader will be notified to load; the child loader will repeat this step. If it can't be loaded to the bottom layer, throw an exceptionClassNotFoundException

Summary :All loading requests will be transmitted to the root loader to load, only when the parent loader cannot be loaded, the sub-class loader will load

image-20210424172312780

effect

  • Avoid repeated loading of classes
  • Ensure the security of the Java core class library

5. How to break the parental delegation mechanism

image-20210429223015451


image-20210429223410292

How to break the parental delegation mechanism?

[JVM notes] How to break the parent delegation mechanism

Destroy the Parental Delegation Model-简书(jianshu.com)

1️⃣First destruction

Since the parent delegation model was introduced after JDK1.2, the class loader and abstract class java.lang.ClassLoader already existed in the JDK1.0 era, facing the implementation of existing user-defined class loader Code, Java designers had to make some compromises when introducing the parental delegation model. Prior to this, the only purpose of the user to inherit java.lang.ClassLoader was to rewrite the loadClass() method, because the virtual machine would call the loader's private method loadClassInternal() when the class was loaded, and the only logic of this method was To call your own loadClass().

2️⃣ second destruction

The second "destruction" of the parental delegation model is caused by the defects of the model itself. Parental delegation solves the same problem of the basic classes of each class loader (the more basic classes are determined by the higher-level loader Load), the basic classes are called "basics" because they are always used as APIs called by user code, but things in the world are often not absolutely perfect.

A typical example is JNDI service, JNDI is now a standard service for Java

JNDI (Java Naming and Directory Interface, Java Naming and Directory Interface) is a standard Java naming system interface provided by SUN . JNDI provides a unified client API, through different access provider interfaces JNDI service supply interface ( SPI) To achieve, the manager maps the JNDI API to a specific naming service and directory system, so that Java applications can interact with these naming services and directory services .

Its code is loaded by the startup class loader (rt.jar put in when JDK1.3), but the purpose of JNDI is to centrally manage and find resources, it needs to call the implementation of independent vendors and deploy in the application The code of the JNDI interface provider under ClassPath, but it is impossible for the startup class loader to "recognize" these codes.

In order to solve this problem, the Java design team had to introduce a less elegant design **: thread context class loader** Thread Context ClassLoader. This class loader can be set by the setContextClassLoader() method of the java.lang.Thread class. If it has not been set when the thread is created, it will inherit one from the parent thread. If it has not been set in the global scope of the application If so, then this class loader is the application class loader by default.

image-20210424190356182


With the thread context loader , the JNDI service can use to load the required SPI code, that is, the parent class loader requests the child class loader to complete the class loading action. This behavior actually opens up the parent delegation model hierarchy The structure to reverse the use of class loader has actually violated the general principle of the parental delegation model, but this is also helpless. Basically, all loading actions involving SPI in Java use this method, such as JNDI, JDBC, JCE, JAXB, and JBI.

3️⃣ third destruction

The third "destroyed" of the parent delegation model is caused by the user's pursuit of program dynamics. The "dynamic" mentioned here refers to some very "hot" terms: hot code replacement, hot module deployment Wait, the short answer is that the machine does not need to be restarted, it can be used as long as it is deployed.
The key to OSGi's modular hot deployment is the realization of its custom class loader mechanism. Each program module (Bundle) has its own class loader. When a Bundle needs to be replaced, the Bundle and the class loader are replaced together to achieve hot code replacement. In the illusion of OSGi, the class loader is no longer a tree structure in the parental delegation model, but has further developed into a more complex network structure. When a class loading request is received, OSGi will perform a class search in the following order:
1 ) Delegating classes starting with java.* to the parent class loader to load.
2) Otherwise, the classes in the delegation list are delegated to the parent class loader to load.
3) Otherwise, delegate the class in the Import list to the class loader of the Bundle of the Export class to load.
4) Otherwise, find the ClassPath of the current Bundle and use your own class loader to load it.
5) Otherwise, find out whether the class is in its own Fragment Bundle, and if it is, it will be delegated to the Fragment Bundle's class loader to load it.
6) Otherwise, find the Bundle in the Dynamic Import list and delegate to the class loader corresponding to the Bundle to load.
7) Otherwise, the class loader fails.


6. How does jvm determine the object to be recycled

1. Reference counting method

Each object has a reference count attribute, a new reference count plus 1 is added, the count decrements when the reference is released, and it can be recycled when the count reaches 0

This algorithm is not used in the current JVM, because it does not solve the problem of circular references between objects

Suppose there are two objects A and B refer to each other, the reference counts of the two objects are not 0, and they cannot be recycled.
public class Main {
public static void main(String[] args) {
MyObject A = new MyObject();
MyObject B = new MyObject();
A.object = B;
B.object = A;
A = null;
B = null;
System.gc();//不能将A、B对象进行回收
}
}

2. Accessibility analysis method (root backtracking method)

Due to the shortcomings of the reference counting method, the reachability analysis method is introduced, which determines whether the object can be recycled by judging whether the reference chain of the object is reachable.

Starting from GC Roots and searching downwards, the searched path is called the reference chain. When an object is connected to the GC Roots without any reference chain, it is proved that the object is unreachable, and the JVM judges it as a recyclable object

image-20210526085856721

The objects of GC Roots are:

  • Objects referenced in the virtual machine stack (local variable table in the stack frame)
  • Objects referenced by static properties of the class in the method area
  • Objects referenced by constants in the method area
  • Objects referenced by the native method stack JNI (NATIVE native method)

The unreachable object in the reachability algorithm does not die immediately , and the object has a chance to save itself. The object is declared dead by the system to go through at least two marking processes: the first time is through the reachability analysis and it is found that there is no reference chain connected to GC Roots, and the second time is to determine whether it is necessary in the Finalize queue automatically established by the virtual machine Execute finalize() method

When an object becomes unreachable, the GC will determine whether the object has covered the finalize() method, and if it is not covered, it will be recycled directly. Otherwise, if the object has not executed the finalize method, it is put into the F-Queue queue, and a low-priority thread executes the finalize method of the object in the queue. After the finalize method is executed, the GC will again determine whether the object is reachable, and if it is unreachable, it will recycle; otherwise, the object will be resurrected

Note: Each object can only trigger the finalize method once. In addition, the finalize method is expensive to run, and the uncertainty is also great, and the calling order of each object cannot be guaranteed, so generally it will not be overwritten.


7. JVM determines when to reclaim the object after it is reclaimed

  • Will automatically recycle when the cpu is idle
  • After the heap memory is full
  • Try to recycle after actively calling System.gc()

8. How to recycle jvm

GC garbage collection is mainly in the young and old generations. First of all, the object was born in the Eden Park. The area can only store a certain number of objects. When it is full, a light GC will be triggered to empty the Eden Park. After cleaning, some objects may still have references and survive and enter the survival area; This reciprocation, if the object has gone through 15 -XX:MaxTenuringThreshold=nGCs in the young generation ( parameters can be set ) and has not died, it will enter the old generation. When the old generation is full, a heavy GC will be triggered . The objects in the young generation + the old generation will be cleaned up. The new generation + old generation are full, then OOM

Minor GC: Light GC, triggered when the Eden Park is full; reclaim memory from the young generation

Full GC: Heavy FC, triggered when the old generation is full; clean up the entire heap space, including the young generation and the old generation

How to recycle refers to the algorithm of garbage collection. There are four algorithms:

1. Mark-and-sweep algorithm

This is the most basic algorithm, which is divided into two steps. The first is marking, that is, all the objects that need to be recycled at the marked place. After marking is completed, the marked objects will be recycled in a unified manner.

The advantage of this algorithm is simplicity, the disadvantage is efficiency, and the biggest disadvantage is the space problem. After the mark is cleared, a large number of discontinuous memory fragments will be generated, which cannot be found when the program needs to allocate larger objects in the future running process. Enough contiguous memory and waste of memory space

2. Copy Algorithm

Copying divides the available memory into two equal-sized blocks by capacity, and only uses one block at a time. When this block of memory is used up, the surviving objects are copied to another block, and then the used memory space is cleaned up at once. In this way, one piece of memory is reclaimed every time, and there is no need to consider complex situations such as memory fragmentation when memory is allocated. It's just that the price of this algorithm is to reduce the memory to half of the original

3. Mark-compression algorithm

The mark-sweeping algorithm is very similar to the mark-sweeping algorithm, but the most significant difference is: the mark-sweeping algorithm only processes non-surviving objects, and the remaining surviving objects do not do any processing, causing memory fragmentation; while the mark-sweeping algorithm does not only deal with non-surviving objects. Perform processing and cleaning, and also organize and reorganize the remaining surviving objects, so it will not generate memory fragmentation

4. Generational collection algorithm

The generational collection algorithm is a relatively intelligent algorithm, and it is also the most used algorithm in jvm. It is not a new algorithm itself, but it will automatically select the above three algorithms for garbage object collection in specific scenarios.

image-20210331122324505

9. System.gc()

System.gc()Used to call the garbage collector, the function of the System.gc() function is only to remind or tell the virtual machine that it hopes to perform a garbage collection. As for when the collection is performed, it depends on the virtual machine, and there is no guarantee that the collection will

image-20210331110948319


actually be called. Runtime.getRuntime().gc()Methods, Runtimesome commonly used methods in the class:

static RuntimegetRuntime() returns the runtime object associated with the current Java application
longmaxMemory() returns the maximum amount of memory that the Java virtual machine will try to use
longtotalMemory() returns the total amount of memory in the Java virtual machine
public class Test {
    public static void main(String[] args) {
        //返回jvm试图使用的最大内存
        long max = Runtime.getRuntime().maxMemory();
        //返回jvm的初始化内存总量
        long total = Runtime.getRuntime().totalMemory();
        //默认情况下:分配的总内存为电脑内存的1/4,初始化内存为电脑内存的1/64
        System.out.println("max=" + max / (double) 1024 / 1024 / 1024 + "G");
        System.out.println("total=" + total / (double) 1024 / 1024 / 1024 + "G");
    }
}
image-20210331111744461


Among them gc()is a native method that calls the underlying C/C++ library


10. JVM performance tuning

Reference : Detailed JVM tuning tool

The JDK comes with many monitoring tools, which are located in the bin directory of the JDK. Among them, the two most commonly used view monitoring tools are jconsole and jvisualvm.

  • jconsole: used to monitor the memory, threads and classes in the JVM;
  • jvisualvm: The all-round analysis tool that comes with the JDK, which can analyze: memory snapshots, thread snapshots, program deadlocks, monitoring memory changes, gc changes, etc.

1️⃣Set jvm tuning parameters

-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
  • -XmxUsed to set the maximum memory that jvm tries to use, the default is 1/4
  • -XmsUsed to set the jvm initialization memory, the default is 1/64
  • -XX:+HeapDumpOnOutOfMemoryErrorIndicates that when OOM occurs in the JVM, a DUMP file is automatically generated

2️⃣Through java's own jvm tuning and diagnostic tool jvisualvm

The all-round analysis tool that comes with JDK can analyze: memory snapshot, thread snapshot, program deadlock, monitoring memory changes, gc changes, etc.

D:\JAVA_Environment\jdk\jdk1.8\bin>jvisualvm

D:\JAVA_Environment\jdk\jdk1.8\bin>

The launcher has determined that the parent process has a console and will reuse it for its own console output.
Closing the console will result in termination of the running program.
Use '--console suppress' to suppress console output.
Use '--console new' to create a separate console window.
image-20210510222056937

3️⃣Using the memory snapshot tool JProfiler to analyze the dump file

The Dump file is a memory image of the process, and the execution state of the program can be saved to the dump file through the debugger.

Use the memory snapshot tool JProfiler to analyze Dump memory files, quickly locate memory leaks; obtain files in the heap; obtain large objects...

# 配置当JVM发生OOM时,自动生成DUMP文件(.hprof)
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

4️⃣ Arthas tools

Arthas user documentation — Arthas 3.5.0 documentation (gitee.io)


11. JVM tuning parameters

  • -Xms2g: The initial push size is 2g;
  • -Xmx2g: The maximum heap memory is 2g;
  • -XX:NewRatio=4: Set the memory ratio of the young and old generations to 1:4;
  • -XX:SurvivorRatio=8: Set the ratio of Eden and Survivor of the new generation to 8:2;
  • -XX:+UseParNewGC: Specify the use of the ParNew + Serial Old garbage collector combination;
  • -XX:+UseParallelOldGC: Specify the use of the ParNew + ParNew Old garbage collector combination;
  • -XX:+UseConcMarkSweepGC: Specify the CMS + Serial Old garbage collector combination;
  • -XX:+PrintGC: Turn on printing gc information;
  • -XX:+PrintGCDetails: Print gc detailed information.