The JVM is the foundation of the Java programmer’s foundation, and it is the core module of all kinds of Java job interviews in the market, so the importance of a thorough understanding of the JVM is self-evident. This chapter starts with the JVM architecture, which is disassembled into class loading modules, JVM execution engine modules, and JVM memory structure modules. This article will try to explain the following issues:

  1. What are the overall architecture of the JVM and the functional boundaries of its core modules?
  2. What is the entire loading process for a class?
  3. What is the process of creating and accessing objects?
  4. How does the JVM do object garbage collection?

If you want to understand the JVM, you should start with the ARCHITECTURE of the JVM. You should have a map of the entire JVM, and then dive into the principles of specific modules.

The JVM architecture

JVM class loading mechanism

Class loading process

loading

  • Loading time

Before creating an object, the JVM checks whether the class is loaded, looks for the corresponding class object, and allocates memory for your object if it is loaded. Initialization is the code :new Object().

Instead of waiting for a class to be “first actively used” before loading it, the JVM specification allows the classloader to preload a class in anticipation of it being used, and if it encounters a missing.class file or an error during preloading, The class loader must not report a LinkageError until the program first actively uses the class. If the class is never actively used by the program, the class loader will not report an error.

When the class name.class is executed, the JVM checks to see if the class object is loaded into memory. If it is not, the class object is loaded into memory, and then the class object is returned. If it is, the class object is returned directly. After a Class object is loaded, it is not initialized. (Static code is not executed and initialized)

When class.forname () is executed, the JVM also checks to see if the Class object is loaded into memory. If it is not, the Class object is loaded into memory, and then the Class object is returned. If it is, the Class object is returned directly. After a Class object is loaded, the Class is initialized by executing a static block of code for the Class. The argument in the forName() method is the class name string, which = package name + class name. A very common use of class.forname () is when the database driver is loaded.

  • The loading process
  1. The class loader reads the binary byte stream of a class through its full-path qualified name. (Go to the corresponding directory of the file system.)
  2. Converts the class structure represented by the binary byte stream into the method section of the runtime data section.
  3. Generate java.lang.Class instances (Class objects) representing this Class in the heap (loaded from the.class file and placed in the heap). The end product of Class loading is the Class object in the heap, which encapsulates the Class’s data structure in the method area and provides the Java programmer with an interface to access the data structure in the method area.

After the loading phase is complete, the binary byte streams outside the virtual machine are stored in the method area in the format required by the virtual machine, and an object of java.lang.Class is created in the Java heap through which the data in the method area can be accessed.

  • Class object

There are two types of objects in Java: Class objects and instance objects, which are instances of classes, usually built with the new keyword. The Class object is the information that the JVM generates about the Class that holds the object. Java programs are compiled, loaded, linked, and initialized before execution. In the compilation phase, the source file is compiled into a. Class bytecode file, and the compiler generates class objects in the. Class file. In the loading phase, class objects are loaded into memory through the JVM’s internal class loading mechanism. Before creating an object instance, the JVM checks to see if the Class object exists in memory. If not, it loads the Class object and then creates the object instance. If it does, it creates the object instance directly from the Class object. There is only one Class object in the JVM, but multiple object instances can be generated from a Class object.

  • Load strategy (parental delegation model)

If a class loader receives a request for a class load, it first does not load the class itself. Instead, it delegates the request to the parent class loader, at each level, so that all load requests are sent to the top level of the starting class loader. The child loader attempts to load the class only if the parent loader cannot complete the load request (it cannot find the required class in its search scope). Here’s a well-known example of why the parent delegate model is used:

The hacker customizes a java.lang.String class that has the same functionality as the system’s String class, with a few modifications in one function. Consider equals, which is often used if hackers add “virus code” to the equals function. And added to the JVM via a custom class loader. At this point, without the parental delegation model, the JVM might mistake the hacker’s custom java.lang.String class for the system’s String class, causing “virus code” to be executed.

With the parental delegation model, hacker-defined java.lang.String classes are never loaded into memory. Because the topmost classloader first loads the system’s java.lang.String class, the custom classloader ultimately cannot load the java.lang.String class.

The essential principle is that the built-in classes of the system are not allowed to be copied. First look for the built-in classes of the system.

The connection

  • validation

Ensure that the byte stream in the Class file meets the requirements of the current VM and does not compromise vm security.

  • To prepare

Allocate memory for class variables (static modifications) in the method area. It then initializes the value ** (the default value for the corresponding data type) **** and assigns it directly if the class variable is constant < modified by final >, otherwise it is the default zero value for the Java type. ** Instance variables are allocated in the Java heap along with the object when it is instantiated.

  • parsing

The class file constant pool is used to store two major types of constants: literals and Symbolic References.

Literals: Values that appear directly in Java source code, including integers, floating point numbers, single characters in single quotes, strings in double quotes, and reserved words true, false, and NULL. Example: 1 1.0 ‘1’ “one” true false NULL.

Symbolic References** : Symbolic References describe the referenced target as a set of symbols, which can be any form of literal, as long as they can be used unambiguously to locate the target.

For example, it appears in Class files as constants of the types CONSTANT_Class_info, CONSTANT_Fieldref_info, CONSTANT_Methodref_info, etc. Corresponding to the following three types of constants:

  • Class and interface and fully qualified name: For the String class, for example, the fully qualified name is Java /lang/String.
  • Field names and descriptors: Fields are variables declared in a class or interface, including class-level variables (static) and instance-level variables.
  • Method name and descriptor. A descriptor is equivalent to a method’s parameter type + return value type.

** Java.class files consist of: ** literals, symbolic references, and the Java language.

In Java, a Java class will be compiled into a.class file. At compile time, the Java class does not know the actual address of the referenced class, so it has to use symbolic references instead. For example, org.simple.People refers to org.simple.Language. At compile time, People does not know the actual memory address of Language, so it can only use the symbol org.simple.Language (assuming this, Of course, it is actually represented by a constant like CONSTANT_Class_info) to represent the address of the Language class.

Symbolic reference is a string, as long as we in the code references an non literal, whether it is a variable or constant, it is defined by a string of symbols, the string in the constant pool, class loading when loaded into this symbol for the first time, will be the symbol references (string) into direct reference (pointer).

Initialize the

Initialize the class variable (static). Static code block execution.

JVM Execution Engine

Java bytecode compilation execution

Back in JDK1.0, it was more accurate to characterize the Java language as “interpreted execution” (first compiled into bytecode and then performed interpreter line-by-line interpretation of bytecode). Later, Java also developed compilers that could directly generate native code (in this case, the back-end compiler JIT, which compiles source code directly into the machine language specific to the local machine platform) and now the JVM executes Java code in a combination of interpreted execution and compiled execution. Java today uses a mixture of interpret and compile:

The execution engine gets it, and the javac compiles the source code into a bytecode file class. It is then converted to the final machine code at run time through the interpreter. (Explanatory)

In addition, the JVM platform supports a technique called just-in-time compilation. The purpose of just-in-time compilation is to avoid the function being interpreted and instead compile the whole function body into machine code, which can make execution much more efficient (direct compilation).

Interpretor features

As the name suggests, the virtual machine translates. Class files into native machine code while executing the corresponding instructions. Interpretation execution is generally used in the case of low memory and low hardware conditions.

  • Explain the advantages of execution:

A) Occupies less resources

B) Fast startup speed

  • Explain execution shortcomings

A) Unnecessary resources will be wasted if the code has to be translated every time it is executed

B) The performance is not stable, and the code is translated every time it is executed, which increases the probability of problems in the translation process

JIT (Just In Time Compiler) features

It’s a new mode from Hotspot. In this compilation mode, the code is compiled into a native machine code file and stored in memory. The next time the code needs to be executed, the corresponding native machine code is fetched directly from memory. The JIT mode is often used on devices with abundant resources such as memory. The Server mode of the JVM uses a mixture of JIT and compile mode. When the program runs, the JVM runs in interpreted mode, and if it encounters code that has been executed more than once, it marks it as hot code and then executes it in JIT mode.

  • Advantages of JIT mode:

A) Fast to run

B) Only need to compile once, stable performance

  • Disadvantages of JIT mode

A) Occupy a lot of resources such as memory

B) The startup speed is relatively slow

Reference: juejin. Cn/post / 685457… recommended

The garbage collection

Determines whether an object needs to be reclaimed

  • Reference counting algorithm

The circular reference scenario causes a memory leak.

public class ReferenceCountingGC { public Object instance; public ReferenceCountingGC(String name){} } public static void testGC(){ ReferenceCountingGC a = new ReferenceCountingGC("objA"); ReferenceCountingGC b = new ReferenceCountingGC("objB"); a.instance = b; b.instance = a; a = null; b = null; } If a/ B. execute is released first and then a/ B execute is released, there will be no memory leak. If the a/ B reference is released, the A/B object cannot be found and the A/B.instance reference cannot be released again.Copy the code

  • Accessibility analysis

The basic idea of Reachability Analysis is to search down from these nodes using GC Roots as the starting point, and the path is called the Reference Chain. When an object is not connected to GC Roots by any reference chain (that is, unreachable from the GC Roots node to the node), the object is proved to be unavailable.

The Gc Roots:

  • Object reference in the virtual machine stack ****. < Object references in the heap are not used as GC Root>
  • A static **** object reference in the method area.
  • Object references to constants in the method area.
  • Object references to JNI (commonly referred to as Native methods) in the Native method stack.

Reference: www.infoq.cn/article/ZOY…

Recovery algorithm

  • Tag clearing algorithm < prone to memory fragmentation >

  • Replication algorithm < space utilization low >

The memory space is divided into 1 area and 2 area. The JVM marks the reachable object and copies it to cell 2, where cell 1 is cleared.

  • Tag collation algorithm < inefficient >

The mark-Compact marking process is still the same as the mark-clean algorithm, but instead of cleaning up the recyclable objects directly, the next step is to move all surviving objects to one end and clean up the memory area beyond the end boundary. On the one hand, the mark-clean algorithm is upgraded to solve the problem of memory fragmentation, and avoids the drawback that the copy algorithm can only use half of the memory region. It looks nice, but as you can see from the figure above, it changes memory more frequently and needs to sort out all references to living objects, which is much less efficient than the copy algorithm.

  • Generation collection algorithm

  • The JVM heap structure

  • Each region recovery algorithm

Generational Collection is not strictly an idea or theory, but a combination of three basic algorithm ideas and different algorithms for different situations. The JVM divides memory into chunks based on object lifetime. Typically, the Java heap is divided into the new generation and the old generation, so that the most appropriate collection algorithm can be used for each generation. In the new generation, a large number of objects are found dead and only a few survive in garbage collection, so the replication algorithm is selected, and only a small amount of the replication cost of the surviving objects can be collected. In the old days, because the object has a high survival rate and there is no extra space to allocate it, it must be recycled using mark-clean or mark-tidy algorithms.

  • Young area

  • Principle of regional division

Why survivor is needed

Isn’t it better to go from the new generation to the Old age? Why is it so complicated? Imagine if there were no Survivor zones, and every time a Minor GC was performed in Eden, the surviving objects would be sent to the old age, which would quickly fill up. There are a lot of objects that don’t get killed in one Minor GC, but don’t really last long, and may need to be wiped out in the second or third. Moving to the elderly area at this time is clearly not a wise decision. Thus, Survivor exists to reduce the number of objects sent to the old age, thus reducing the occurrence of Major GC. Survivor pre-screening guarantees that only objects that survive 16 Minor GC’s will be sent to the old age.

Why two (including from and to)

The biggest benefit of having two Survivor zones is resolutionSurvivor areaMemory fragmentation.

Let’s assume for a second what happens to Survivor if there’s only one region. After the Minor GC is executed, the Eden region is cleared, and the surviving objects are placed in the Survivor region, and some of the objects in the Survivor region may also need to be cleared. The question is, how do we get rid of them? In this scenario, we can only mark clear, and we know that the biggest problem with mark clear is memory fragmentation, which is bound to result in severe memory fragmentation in areas that often die out in the new generation. Since Survivor has two zones, each Minor GC copies surviving objects From the previous Eden and From zones To the To zone. On the second Minor GC, the From and To responsibilities are converted, and the living objects in Eden and To are copied To the From region, and so on.

  • Old area:

  • Recycling mechanism

Older generations occupy two-thirds of The heap and are only cleaned up during Major GC, which triggers “stop-the-world”. The larger the memory, the longer the STW, so it’s not just that bigger memory is better. Because the replication algorithm will carry out many replication operations in the old age when the object survival rate is high, the efficiency is very low, so the mark-collation algorithm is used here in the old age.

Reference:

www.infoq.cn/article/ZOY…

Mp.weixin.qq.com/s/aA1eDYIUH…

Blog.csdn.net/aaa1117a8w5…

www.kancloud.cn/imnotdown10…

The GC to perform

  • GC type

For the HotSpot VM implementation, there are actually only two types of GC that are accurate:

  • Partial GC: Mode that does not collect the entire GC heap

  • Young GC: Only Young Gen’s GC is collected.

  • Old GC: Only Old Gen GC is collected. Only concurrent collection from CMS is in this mode.

  • Mixed GC: Collects GC for all young Gen and part of old Gen. Only the G1 has this mode.

  • Full GC: Collects the entire heap, including all parts of young Gen, Old Gen, Perm Gen (if any), and so on.

The Major GC is usually equivalent to the full GC, collecting the entire GC heap.

However, since HotSpot VM has been around for so many years, the interpretation of various terms has become completely confusing. When someone says “major GC”, be sure to ask if they mean full GC or old GC.

Ant internal mode: Yong GC + Full GC, without Old GC and Mixed GC

Reference: www.zhihu.com/question/41…

  • Condition that the object enters the old section

When the object is created for the first time, it will be placed in Eden area of the new generation. If GC is not involved, it will remain in Eden area. After GC, it may enter survivor area or old generation:

  • * * Survivor area. **yong After GC, the remaining space in survivor zone is insufficient to hold viable objects in Eden zone.

  • Long-lived objects. When the object reaches a certain age, it will leave the younger generation and enter the old age. The age of an object is determined by the number of GC cycles. -xx :MaxTenuringThreshold=n The age of an object is determined by the number of GC cycles. < Default is 16 hops >

  • Large object **, reduce the replication cost from to ****. In addition to age, object size also affects the promotion of objects, if the object size is too large, the replication cost is very high. * * – XX: PretenureSizeThreshold namely object size is greater than this value, can bypass the Cenozoic, in old age distribution directly.

  • Full GC trigger condition

  • When you are about to trigger a Young GC, if the statistics say that the average promotion size of the previous young GC is larger than the remaining space of the current Old Gen, the Young GC will not trigger but will trigger full GC instead.

  • A large object directly applies for space in the old space and finds that the memory in the old space is insufficient.

Memory leaks and memory overflows

Why do YOU need to know about memory leaks and memory spills?

  1. Memory leaks are usually caused by code design defects. By understanding the scenarios of memory leaks, you can avoid unnecessary memory leaks and improve your code writing skills.
  2. By learning the common memory overflow cases, you can quickly locate the fault and shorten the troubleshooting time.

A memory leak

In Java, a memory leak is the existence of some allocated objects. These objects have the following two characteristics. First, these objects are reachable, that is, in the directed graph, there are channels to connect to them. Second, these objects are useless, that is, the program will never use them again. If an object meets these two conditions, it can be considered a memory leak in Java; it will not be collected by GC, but it will consume memory.

Long-life objects hold references to short-life objects

This is the most common scenario for memory leaks and is a common problem in code design. For example, if local variables are cached in a global static map and no clearing operation is performed, the map will grow larger over time, resulting in memory leaks.

Static Vector v = new Vector(10);
for (int i = 0; i < 100; i++) {
    Object o = new Object();
    v.add(o);
    o = null;
}
Copy the code

In this example, we loop through the Object and put it into a Vector. If only the reference itself is freed (o=null), the Vector still refers to the Object, so the Object is not recoverable by the GC. Therefore, if an object is added to a Vector, it must be deleted from the Vector. The simplest way to do this is to set the Vector to NULL.

Out of memory

An error that occurs when a program fails to obtain enough memory.

Heap overflow

After full GC, if Survivor and Old zones still cannot store some objects copied from Eden, so that JVM cannot create a memory region for the new objects in Eden zone, an “out of memory error” will occur: outOfMemoryError: java heap space

The solution

First, if there are no problems with your code, you can adjust the -xms and -xmx JVM parameters appropriately, using stress tests to adjust them to the optimal values. ** Second, try to avoid the application of large objects, such as file upload, large quantities of data from the database, this is to avoid, try to block or batch processing, conducive to the normal and stable implementation of the system. Finally, try to speed up the execution of a request, garbage collection as early as possible, otherwise, when a large number of concurrent requests, new requests will not be able to allocate memory, easy to cause the system avalanche.

Method area memory overflow

OutOfMemoryError: permgem space, java8 for Java. Lang. OutOfMemoryError: Metaspace

Dimension of overflow, the system will be thrown. Java lang. OutOfMemoryError: Metaspace. The reason for this exception is that the system has a lot of code or a lot of third-party packages referenced or through dynamic code generation class loading, which leads to a lot of memory in the meta-space.

The solution

By default, the size of a meta-space is limited only by local memory. But for the performance of the whole machine, try to set the item, so as not to cause the service shutdown of the whole machine.

1) Optimize parameter configuration to avoid affecting other JVM processes

-xx :MetaspaceSize, the initial size of the space, which triggers garbage collection for type offloading and is adjusted by the GC: if a large amount of space is freed, the value is reduced appropriately; If very little space is freed, increase this value appropriately until MaxMetaspaceSize is exceeded.

-xx :MaxMetaspaceSize. The maximum space is unlimited by default.

In addition to the two options above to specify the size, there are two gC-related attributes:

-xx :MinMetaspaceFreeRatio, the minimum percentage of Metaspace free space capacity after GC to reduce garbage collection resulting from space allocation.

-xx :MaxMetaspaceFreeRatio, the maximum percentage of Metaspace free space capacity after GC, reduced to garbage collection caused by free space.

2) Use third-party packages with caution

For third-party packages, be sure to choose carefully and remove unnecessary packages. This helps speed up both compilation packaging and remote deployment.

3) Focus on frameworks that generate classes dynamically

For frameworks that use a large number of dynamically generated classes, do stress tests to see if dynamically generated classes exceed memory requirements and throw exceptions.

Thread stack overflow (Java. Lang. StackOverflowError)

When a thread executes a Java method, the JVM creates a new stack frame and pushes it to the top of the stack. The new stack frame becomes the current stack frame, which is used to store parameters, local variables, intermediate instructions, and other data as the method executes. When a method calls itself recursively, the data generated by the new method (also known as the new stack frame) is pushed to the top of the stack, and each time the method calls itself, a copy of the current method’s data is pushed onto the stack. Therefore, each layer of recursive calls needs to create a new stack frame. As a result, more and more memory in the stack will be consumed with recursive calls, and if recursive calls themselves a million times, a million stack frames will be generated. This will cause stack memory overflow.

The solution

If there are recursive calls in the program and stack overflow occurs, you can increase the -xSS size and solve the stack overflow problem. Recursive calls prevent an infinite loop that would otherwise run out of stack memory.

Runtime data area

In JDK1.6 and before, the runtime constant pool contained a string constant pool stored in the method area, where the hotspot virtual machine implemented the method area as a permanent generation.

In JDK1.7 the string constant pool is taken from the method area to the heap, there is no mention of the runtime constant pool, that is, the string constant pool is taken to the heap separately, what is left of the runtime constant pool is still in the method area, which is the permanent generation in hotspot.

In JDK1.8 hotspot the permanent generation is removed and replaced with a meta-space, where the string constant pool is still in the heap and the runtime constant pool is still in the method area, but the implementation of the method area is changed from the permanent generation to the meta-space (out-of-heap memory).

JDK1.7

JDK1.8

JVM Data store

Class data

  • The location of java.lang.Class objects and static member variables in runtime memory.

In JDK 1.8, both are in the Heap, and static member variables are in the Class object. We know that in the five processes of Class Loading, the end product of Loading is a java.lang.Class object, which is our external interface to the type data in the method area. We need this object to access the class’s fields, methods, run-time constant pool, and so on.

  • Class metadata

JDK 1.8, stored in the metadata area.

Reference: blog.csdn.net/wushiwude/a…

Base and reference type variables

As above.

Constant pool

  • Class file constant pool

The class file constant pool stores literal and symbolic references that are stored in the method area when class files are loaded by the Java virtual machine. Literals include strings, primitives, and constants.

  • Runtime constant pool (in the methods area, 1.7 in the persistent generation, 1.8 in the metadata area)

When a Java file is compiled into a class file, which generates the class constant pool I mentioned above, when is the runtime constant pool generated?

When a JVM executes a class, it must go through loading, wiring, and initialization, and wiring includes three phases: validation, preparation, and parsing. When a class is loaded into memory, the JVM stores the contents of the class constant pool into the runtime constant pool, which is also one for each class. As I mentioned above, class constant pools store literals and symbolic references, which means they don’t store instances of objects, but rather symbolic reference values of objects. Resolve, which replaces symbolic references with direct references, queries the global string pool, known as StringTable, to ensure that the strings referenced by the constant pool at run time are the same as those referenced by the global string pool.

The method section stores the class file information and the runtime constant pool. The class file information includes class information and the class file constant pool. In addition to the contents of the class file constant pool, the runtime constant pool transforms symbolic references in the class file constant pool into direct references.

  • String constant pool (1.6 with run-time constant pool, 1.7 moved to the heap)

The contents of the global string pool are generated in the heap after class loading, validation, and preparation, and then the reference value of that string object instance is stored in the String pool (remember: The string pool holds reference values instead of specific instance objects, which are stored in a chunk of the heap. . The string pool implemented in HotSpot VM is a StringTable class, which is a hash table that holds references to the resident string (often quoted) rather than the resident string instance itself. That is, if some string instance in the heap is referenced by this StringTable, it is given the status of “resident string.” This StringTable has only one copy per HotSpot VM instance, shared by all classes.

The value can be adjusted using the -xx :StringTableSize parameter.

Here’s an example:

Strings str1 = "ABC"; String str2 = new String(" def "); String str3 = "ABC"; String str5 = new String(" ABC ");Copy the code

After the above program is compiled, some symbolic references are stored in the class constant pool of the class. After the class is loaded, the symbolic references stored in the class constant pool are dumped into the runtime constant pool. Generate the instance object that resides the String in the heap (that is, the “ABC” instance object pointed to by str1 in the above example), store the reference to that object in the global String Pool, which is called StringTable, and finally, during parsing, replace symbolic references in the runtime constant Pool with direct references. So you just query StringTable and make sure that the references in StringTable match the references in the runtime constant pool, and that’s about it.

Going back to the above program, it is now easy to explain how the entire program allocates memory. First, there is an instance of “ABC” in the heap, and the global StringTable holds a reference to “ABC”. Then when we run the second sentence, we generate two instances, one of which is an instance object of “def”. And StringTable stores a reference to “def”, and a new instance object of “def”, which is a different instance. When parsing str3, look up StringTable, which contains a globally resident string reference to “ABC”. Str4 calls intern() at run time and returns a reference to “def” in StringTable. If it does not, it adds a reference to str2. StringTable already has a reference to “def”, so return the “def” reference added to StringTable in new str2. Str5 will parse the reference to “def” in StringTable. After this analysis, the following three printed values are easy to understand.

Reference: Recommendation

Blog.csdn.net/xiaojin21ce…

www.cnblogs.com/holos/p/660…

  • Wrap class constant pool

Most of the basic types of Java wrapper class implements the constant pool technology, namely, Byte, Short, Integer, Long, Character, and Boolean; These five wrapper classes create the corresponding type of cached data for the value [-128,127] by default, but new objects are still created beyond this range.

The wrapper class Float,Double, for two floating-point types, does not implement constant pooling technology.

Integer i1 = 33; Integer i2 = 33; System.out.println(i1 == i2); // Output true Integer i11 = 333; Integer i22 = 333; System.out.println(i11 == i22); // print false Double i3 = 1.2; Double i2 = 1.2; System.out.println(i3 == i4); / / output is falseCopy the code

Object creation process and access

Object creation

  1. Virtual machine to new instruction. Object obj = new Object();

  2. Locate a symbolic reference to a class in the string constant pool. Class symbol references such as Java. Util. Concurrent. TimeUnit;

  3. Check that symbolic references have been loaded, parsed, and initialized. If not, the class is loaded.

  4. The virtual machine allocates memory for new objects (the amount of memory an object needs is determined after the class is loaded)

  5. Initializing all allocated memory space to zero values (excluding object headers) ensures that the instance fields of an object can be used in Java code without initial values, and the program can access the zero values corresponding to the data types of these fields.

  6. The virtual machine performs necessary Settings on the Object Header, such as which class the Object is an instance of, how to know the metadata information of the class, the hash code of the Object, the age of the generation of the Object, and so on. This information is stored in the Object Header. From the virtual machine’s point of view, a new object has been created, and from the Java program’s point of view, object creation has just begun.

  7. The new instruction is followed by the initialization method, which initializes the object as the programmer wishes.

  8. A truly usable object is not fully generated.

Object access

Reference:

www.ityouknow.com/java/2019/0…

Segmentfault.com/a/119000001…

Blog.csdn.net/shimiso/art…