Java Face Classic 03-Virtual Machines-jvm Memory Structure & Garbage Collection, Memory Overflow & Class Loading, Reference & Pessimistic Lock & HashTable, Reference & finalize

Virtual Machine

1. JVM memory structure

Require

  • Master JVM memory structure division
  • In particular, you must know the relationship between the method area, permanent generation, and metaspace

Combined with the execution of a piece of java code to understand memory division

insert image description here


insert image description here

  • Execute the javac command to compile the source code into bytecode
  • Execute the java command
    1. Create a JVM, call the class loading subsystem to load the class, and store the class information in the method area
    2. Create the main thread, the memory area used is the JVM virtual machine stack , and start executing the main method code
    3. If you encounter an unseen class, it will continue to trigger the class loading process, and it will also be stored in the method area
    4. Objects need to be created, and heap memory will be used to store objects
    5. Objects that are no longer used will be reclaimed by the garbage collector when there is insufficient memory
    6. When calling a method, the local variables and method parameters in the method use the stack frame memory in the JVM virtual machine stack
    7. When calling a method, you must first go to the method area to obtain the bytecode instructions of the method, and the interpreter interprets the bytecode instructions into machine codes for execution
    8. When the method is called, the line number of the instruction to be executed will be read into the program counter , so that when a thread switch occurs, it can continue from the interrupted position when resuming
    9. For non-java-implemented method calls, the memory used is called the local method stack (see description)
    10. For hot method calls, or frequent loop codes, the JIT compiler compiles these codes into machine code caches to improve execution performance (otherwise, every time the same code is executed, the interpreter must repeatedly interpret bytecode instructions as Machine code execution is equivalent to caching bytecode instructions)

Method area: store relevant information of the class (class name, inheritance relationship, symbols of other classes referenced, member variables, method bytecodes, annotations added to classes, methods and member variables, etc.) heap: store new
out The object
JVM virtual machine stack: stores the local variables in the method and the method parameters of the ordinary method variables implemented by java. In the past, special methods that need to interact with the os need to be executed on the local method stack, but now Oracle’s Hotspot virtual machine The implementation no longer uses the local method stack, or the two stacks are combined into one, and the variable memory required by all methods is in the JVM virtual machine stack

illustrate

  • Bold fonts represent JVM virtual machine components
  • For Oracle's Hotspot virtual machine implementation, no distinction is made between the virtual machine stack and the native method stack

Areas where memory leaks can occur

Out of memory: The memory in this area is exhausted, and an error is reported

Memory leak: The garbage collector cannot reclaim a certain part of memory. This phenomenon is called memory leak;

The five memory areas in the above figure, except the program counter, will cause memory overflow

  • The area where memory overflow will not occur – the program counter
  • In case of OutOfMemoryError
    • Heap memory exhaustion – more and more objects are being used all the time and cannot be garbage collected
    • The memory in the method area is exhausted – more and more classes are loaded, and many frameworks will dynamically generate new classes during runtime
    • Virtual machine stack accumulation – each thread will occupy up to 1 M of memory, the number of threads is increasing , and it will not be destroyed when it runs for a long time
  • Areas where StackOverflowError occurs
    • JVM virtual machine stack, the reason is that the recursive call of the method does not end correctly, and the circular reference when deserializing json (the method in the thread is called continuously, and the 1M memory in each thread is consumed, a StackOverflowError will be reported)

Method area, permanent generation, metaspace

  • The method area is a memory area defined in the JVM specification , which is used to store class metadata , method bytecodes , information required by the just-in-time compiler, etc.
  • The permanent generation is the implementation of the JVM specification by the Hotspot virtual machine (before 1.8)
  • Metaspace is another implementation of the JVM specification by the Hotspot virtual machine (after 1.8), using local memory as the storage space for these information

The method area is just a definition in the JVM specification (you have to have it, I don’t care how to implement it). The
permanent generation and metaspace are the physical implementation of the specification.

insert image description here

Learn three things from this picture

Class metadata: The data describing the class (which members, what type, how long...) is stored in the metaspace (the physical implementation of the method area)
class name.class bytecode object, since it is an object, it is naturally stored in the heap
The original information of the class (class metadata) is stored in the metaspace and cannot be accessed directly. It must be accessed through the java object. This object is the bytecode object

  • When a class is used for the first time, the class loader reads the class meta information of the class file and stores it in the meta space
  • The class meta information of X and Y is stored in the meta space and cannot be directly accessed
  • X.class and Y.class can be used to indirectly access class meta information, both of which belong to java objects (bytecode objects), which can be used in our code

insert image description here

From this picture we can learn

  • In heap memory: When a class loader object , all class objects loaded by this class loader object , and all instance objects corresponding to these class objects are not referenced, the heap memory occupied by them will be released during GC
  • In the metaspace: memory is released in units of class loaders . When the memory of the class loader in the heap is released, the corresponding class meta information in the metaspace will also be released

Generally, the system class loader will not be released, and our custom class loader will be released when it is no longer used (what to release? Metaspace memory)

2. JVM memory parameters

Require

  • Familiarity with common JVM parameters, especially those related to size

Question:insert image description here

Heap memory, set by size

insert image description here

explain:

  • -Xms JVM minimum memory (including new generation and old generation)
  • -Xmx JVM maximum memory (including new generation and old generation)
  • It is generally recommended to set -Xms and -Xmx to be equal in size, that is, there is no need to reserve memory, and there is no need to grow from small to large, so the performance is better
  • -XX:NewSize and -XX:MaxNewSize set the minimum and maximum values ​​of the new generation, but it is generally not recommended to set it, and it is controlled by the JVM itself
  • -Xmn sets the size of the new generation, which is equivalent to setting -XX:NewSize and -XX:MaxNewSize at the same time and the values ​​are equal
  • Reservation means that it will not take up so much memory at the beginning, and as more and more memory is used, this part of the reserved memory will be gradually used. Same below

From the perspective of age, JVM divides memory into new generation and old generation
- the n of Xmn is new new generation

Heap memory, set proportionally

New in the figure below is the new generation. The memory of the new generation can be further divided into eden and Survivor. Survivor can be subdivided into: from, to
old, which is naturally the memory of the old generation.

insert image description here

explain:

  • -XX:NewRatio=2:1 means that the old generation occupies two, and the new generation occupies one
  • -XX:SurvivorRatio=4:1 means that the new generation is divided into six parts, Eden occupies four parts, and from and to each occupy one part
  • (Note 1: The default 8:1 is 8:1:1) (Note 2: The above 4:1 refers to eden:from=eden:to=4:1 because from and to are always equal)

Metaspace memory settings

insert image description here

explain:

  • class space stores the basic information of the class, the maximum value is controlled by -XX:CompressedClassSpaceSize
  • non-class space stores information other than the basic information of the class (such as method bytecode, annotations, etc.)
  • The total size of class space and non-class space is controlled by -XX:MaxMetaspaceSize

Notice:

  • Here -XX:CompressedClassSpaceSize This section of space is also related to whether pointer compression is enabled. I won’t go into details here. You can simply think that pointer compression is enabled by default.

Code cache memory settings

JIT instant compiler, which compiles hot code into machine code and caches it, then stores it in the CodeCache code buffer area

insert image description here

explain:

  • If -XX:ReservedCodeCacheSize < 240m, all optimized machine code exists together indiscriminately
  • Otherwise, it is divided into three areas (optimized code is subdivided into 3 parts) (the typo mthod in the figure is misspelled, one e is missing)
    • non-nmethods - code used by the JVM itself (JIT compiler's own code)
    • profiled nmethods - partially optimized machine code
    • non-profiled nmethods - fully optimized machine code

Thread memory settings

That is, the memory of the JVM virtual machine stack
- Xss sets the memory occupied by each thread.
If not set, the Linux system defaults to 1MB, that is, each thread occupies 1MB of memory by default.

insert image description here

Official Reference Documentation

3. JVM Garbage Collection

Require

  • Master the Garbage Collection Algorithm
  • Master the idea of ​​generational recycling
  • Understand the three-color marking and missing label processing
  • Understanding Common Garbage Collectors

eg: Some objects in the heap memory no longer have any references in the stack memory pointing to them, and the GC can recycle them

Three Garbage Collection Algorithms

mark-and-sweep

insert image description here

explain:

  1. Find GC Root objects, that is, objects that must not be recycled, such as objects referenced by local variables in the executing method, objects referenced by static variables
  2. Marking stage: follow the reference chain of the GC Root object, and mark the directly or indirectly referenced objects
  3. Cleanup phase: frees memory occupied by unmarked objects

The object being referenced or used by the local variable must not be recycled and can be used as the root object. The
static variable must always exist and cannot be recycled and can be used as the root object.

Main points:

  • Linear relationship between marking speed and surviving objects
  • Clearing speed is linearly related to memory size
  • The disadvantage is that it will generate memory fragmentation (unmarked memory has a high probability of being discontinuous, and will generate a large amount of memory fragmentation, so it has basically been abandoned)

marking method

insert image description here

explain:

  1. The previous marking phase and cleaning phase are similar to the marking and removal method
  2. One more step of finishing action, moving the surviving objects to one end, can avoid memory fragmentation

Features:

  • Linear relationship between marking speed and surviving objects

  • Clearing and tidying speed is linear with memory size

  • The disadvantage is slower performance

tagged replication

insert image description here

explain:

  1. Divide the entire memory into two areas of equal size, from and to, where to is always free and from stores newly created objects
  2. The marking phase is similar to the previous algorithm
  3. After finding out the surviving objects, they will be copied from from to to area, and the defragmentation will be completed naturally during the copying process (all from area can be cleared after copying)
  4. After the copy is complete, just exchange the positions of from and to (the two areas are used alternately, and there will never be memory fragmentation problems, how good it is)

Features:

  • Marking and replication speeds are linear with surviving objects
  • The disadvantage is that it will take up double the space

GC and generational collection algorithm

The purpose of GC is to realize the automatic release of useless object memory, reduce memory fragmentation, and speed up allocation

GC points:

  • The recovery area is the heap memory , excluding the virtual machine stack (the memory in the method stack, which will automatically release the memory occupied by the method at the end of the method call)
  • Determine useless objects, use reachability analysis algorithm , three-color marking method to mark surviving objects, and recycle unmarked objects
  • The specific implementation of GC is called a garbage collector
  • Most GCs adopt the idea of ​​generational recycling
    • The theoretical basis is that most objects are perishable and can be recycled as soon as they are used up, while a small number of objects will survive for a long time and are difficult to recycle each time
    • According to the characteristics of these two types of objects, the recycling area is divided into the new generation and the old generation . The new generation adopts the mark copy method , and the old generation generally adopts the mark finishing method
  • According to the scale of GC, it can be divided into Minor GC , Mixed GC , and Full GC

New generation: There are many garbage objects (local objects that are often new in the method)
Old generation: There are many surviving objects, which are difficult to recycle, or do not need to be recycled frequently, and the sorting will not be particularly time-consuming (eg: static objects, in the framework Objects used for a long time) (There are many surviving objects in the old generation, and the mark copy method will also waste memory extremely)
Reachability analysis algorithm: find the GC Root and mark it (first find the object that will not be recycled, and then follow its reference chain Find, mark again)
Three-color marking method: see below
There are many types of garbage collectors, see below
.
Minor GC : garbage collection of the new generation, small-scale garbage collection, short pause time, and little impact on the system Full
GC : new generation and The old generation ran out of memory, and a comprehensive garbage collection came. The pause time was long, and the system was obviously stuck. Generally, they did not want to see the Mixed GC of Full GC: It is located between the above two, referring to
: newborn Garbage collection has occurred in the generation, and garbage collection has also occurred in some old generations, a mixed garbage collection, a unique recycling method of the G1 garbage collector

Personally sort out the concepts related to GC and heap memory:
GC just reclaims the
new objects in the heap memory and puts them in the heap memory. Heap
memory division:
From the perspective of age, JVM divides the heap memory into new generation and old generation
. Divided into: eden and Survivor, Survivor can be subdivided into: from, to
first overview, there is a general framework: then slowly look at the detailed process
insert image description here
diagram belowyellowyesidle, the white color is allocated
. Marking can be summed up in one sentence: Find out whether it is directly or indirectly referenced by the root object

Generational recycling

  1. Garden of Eden, where objects are initially allocated here, together with the survivor area (divided into from and to) is called the new generation,

insert image description here

  1. When the memory of Eden is insufficient, mark the surviving objects of Eden and from (not at this stage)

insert image description here

  1. Copy the surviving objects to to using the copy algorithm. After the copy is completed, both the memory of Eden and from are released

insert image description here

  1. swap from and to

insert image description here

  1. After a period of time, the memory of Eden is insufficient again

insert image description here

  1. Mark the surviving objects of Eden and from (not at this stage)

insert image description here

  1. Copy the surviving object to to using the copy algorithm

insert image description here

  1. After copying, both eden and from memory are released

insert image description here

  1. swap from and to

insert image description here

  1. Old generation old, when objects in the survivor area survive several collections (up to 15 times), they are promoted to the old generation (insufficient memory in the survivor area or large objects will lead to early promotion )

Insufficient surviving area: if to is not enough to be copied, it must be moved to the old age (to is very large, the shortage must be due to the existence of objects that have survived recycling before) and there is no way to promote large objects in
advance : Every time the GC has to be copied and copied, it is too consuming, it is better to advance to the old generation in advance

GC scale

  • Minor GC occurs in the new generation of garbage collection, with a short pause time

  • Mixed GC new generation + garbage collection in some areas of the old generation, unique to the G1 collector

  • Full GC new generation + old generation complete (comprehensive) garbage collection, long pause time, should try to avoid

three color mark

That is, the marking state of the object is recorded in three colors

  • black – marked
  • gray – marked
  • white – not marked yet

Black – marked: along the reference chain of the root object, this object has been found, and other references inside this object have also been processed
Gray – marked: along the reference chain of the root object, this object has been found, But other references inside this object have not yet been processed
White - not yet marked: It is the final remaining object that has been marked

  1. The first three objects have not been processed yet, indicated by gray

insert image description here

  1. The reference of the object has been processed, indicated by black, and the object referenced by black turns gray

Mark its direct reference as gray, it is considered that its reference processing is completed, and it can be directly marked as black

insert image description here

  1. And so on

insert image description here

  1. Marked along the chain of references

insert image description here

  1. The last unmarked white object is garbage

insert image description here

Concurrent missing label problem

The previous GC is non-concurrent. When the GC is working, the user thread is suspended, so the user thread will not affect the GC thread. That is,
when the GC is marking, the user thread is suspended and will not have any impact on the marking ( Will not modify the reference chain)
Non-concurrent GC is inefficient, and concurrent GC, that is, concurrent marking, is definitely needed.
Then when the GC is marking, the user thread is still working. In case the user thread modifies the reference relationship during the marking process , it is easy to cause missing marks.

More advanced garbage collectors support concurrent marking , that is, user threads can still work during the marking process. But this brings a new problem. If the user thread modifies the object reference, then there is a problem of missing labels. For example:

  1. Marking work as shown is not yet complete

insert image description here

  1. The user thread is working at the same time, disconnecting the reference between objects 3 and 4 in the first layer. At this time, for the garbage collection thread that is processing object 3, it will treat object 4 as white garbage

It is actually reasonable to recycle 3 at this time
, but in case it is referenced by other objects after it is disconnected (not that we don’t use it, but I use it for others), it cannot be recycled (see below)

insert image description here

  1. However, if other user threads create references to objects 2 and 4, because object 2 is a black processed object , the garbage collection thread will not be aware of the change in the reference relationship , resulting in a missing mark

insert image description here

  1. If the user thread makes the black object refer to a newly added object, there will also be a missing mark problem

The black object has been processed (marked as black, it will be considered as processed), and the object that has been processed will not be processed again (it will not repeatedly find its direct reference and mark it as gray)

insert image description here

Therefore, for concurrent marking , the problem of missing marking must be solved, that is, changes in the marking process must be recorded. There are two workarounds:

The core of solving missing marks is: recording changes in the marking process + secondary processing

  1. Incremental Update incremental update method, the CMS garbage collector uses
    • The idea is to intercept each assignment action. As long as the assignment occurs, the assigned object will be recorded and confirmed again in the remarking stage
  2. Snapshot At The Beginning, SATB original snapshot method, G1 garbage collector uses
    • The idea is to intercept each assignment action, but the recorded objects are different, and these objects need to be processed twice in the remarking stage
    • Newly added objects will be logged
    • Objects whose reference relationship is deleted are also logged

The red arrow black -> white and black object in the above picture is the assigned object (assign the white object to the black object)

insert image description here

Garbage Collector - Parallel GC

  • Minor GC occurs due to insufficient memory in eden, and the mark copy algorithm is used, which needs to suspend user threads

  • Old Full GC occurs due to insufficient memory, and the mark sorting algorithm is used, which needs to suspend user threads

  • Focus on throughput (slower response times and pause times are okay, but overall shorter pause times are ok)

Parallel GC: actually consists of 2 garbage collectors, one works in the young generation, and the other works in the old age
Minor GC. When only the new generation garbage collector works in
the Full GC, both the new generation and the old generation garbage collectors will work
mark copy and Mark finishing (slow) will not have memory fragmentation

Garbage Collector - ConcurrentMarkSweep GC

  • It is a recycler that works in the old age and supports concurrent marking , and uses a concurrent clearing algorithm

    • There is no need to suspend user threads during concurrent marking (may lead to missing marking)
    • It is still necessary to suspend the user thread when re-marking (the user thread can no longer be concurrent when dealing with missing marks, and must be suspended, otherwise it will be endless)
  • If the concurrency fails (that is, the recycling speed cannot keep up with the speed of creating new objects), Full GC will be triggered

  • Pay attention to response time (that is, the benefit of this is that the response time is fast and does not need to wait for a long time)

ConcurrentMarkSweep GC This is an old-age garbage collector.
ConcurrentMarkSweep GC is referred to as CMS garbage collector . Concurrent means that
Concurrent:并发 Mark:标记 Sweep: 扫描,打扫
user threads pause for a short time during GC and can be executed concurrently . It refers to clearing and recycling white garbage objects. However, because people use the mark-and-clear method and have memory fragmentation problems, the latest JDK has marked it as obsolete.

STW(Stop The World)
insert image description here

Garbage Collector - G1 GC

  • Balance between response time and throughput
  • Divided into multiple areas, each area can act as eden, survivor, old, humongous, among which humongous is specially prepared for large objects
  • Divided into three phases: new generation collection, concurrent marking, mixed collection
  • If the concurrency fails (that is, the recycling speed cannot keep up with the speed of creating new objects), Full GC will be triggered

G1 GC reads: G one Garbage collector
humongous: huge

Overview:
insert image description here

G1 also has a guaranteed bottom policy: recycling speed < new object creation speed, that is, concurrent failure: FailBack Full GC performs a recycling as a whole, and the pause time will be longer

G1 Collection Phase - New Generation Collection

  1. Initially, all regions are idle

insert image description here

  1. Some objects are created, and some free areas are selected as the Eden area to store these objects

insert image description here

  1. When Eden needs garbage collection, pick out a free area as the survivor area , use the copy algorithm to copy the surviving objects, and need to suspend the user thread
    (the new generation adopts the mark copy method, copying should be STW, non-concurrent)
    (all surviving objects in the eden area Copy to a survivor area (the to area and then the to and from areas swap status))

insert image description here

  1. After the copy is complete, the previous Eden memory will be released

insert image description here

  1. As time goes by, Eden runs out of memory again

insert image description here

  1. Copy the surviving objects in the Garden of Eden and the previous surviving area to the new surviving area using the copy algorithm, and the older objects are promoted to the old generation

(All objects in the eden area and the surviving from area are copied to the new surviving area (similar to))

insert image description here

  1. Release the memory of Eden and the previous survivor area

insert image description here

G1 collection phase - concurrent mark and mixed collection

The premise is that the memory in the old generation is almost insufficient, and it is necessary to start recycling the old generation. The marking strategy of the old generation is: concurrent marking

  1. When the memory occupied by the old generation exceeds the threshold, concurrent marking is triggered, and there is no need to suspend user threads at this time

insert image description here

It is not to directly reclaim all the old generation areas, but to select a few old generation areas with high recovery value (few surviving objects) to recycle first

  1. After concurrent marking, there will be a re-marking phase to solve the problem of missing marks. At this time, user threads need to be suspended. After all these are completed, we know which surviving objects are in the old generation, and then enter the mixed collection stage. At this time, all the old generation areas will not be recycled, but the areas with high value (less surviving objects) will be recovered first according to the pause time target (this is also the origin of the name Gabage First).

insert image description here

Mixed collection, not only collecting the selected old generation with high recycling value (red in the above picture), but also collecting the new generation (eden+survivor)

  1. In the mixed collection phase, eden, survivor, and old are involved in the replication. The following figure shows the replication of surviving objects in Eden and the survivor area

insert image description here

  1. The figure below shows the replication of surviving objects promoted in the old generation and survivor areas

insert image description here

  1. The copy is complete and the memory is freed. Enter the next round of new generation collection, concurrent mark, mixed collection

insert image description here

4. Out of memory

Out of memory: The memory in this area is exhausted, and an error is reported

Require

  • Be able to name several typical situations that lead to memory overflow

typical situation

  • 1) Memory overflow caused by misuse of thread pool
    • Reference day03.TestOomThreadPool
      insert image description here
      LinkedBlockingQueue is an unbounded queue (Interger type does not overflow, it will not overflow)

insert image description here
The above code continuously creates new sites and submits them. Since each thread has to block for 30ms, the blocking queue is getting bigger and bigger, and it will grow without limit, which will lead to memory explosion.

insert image description here
insert image description here

  • 2) Memory overflow caused by too much query data
    • Reference day03.TestOomTooManyObject

There are too many database entries. If you findAll, you may find 1 million items in one search, which is 1 million very common Product POJO collections, and it also takes up 363MB of memory. No matter how large the server memory is, it cannot withstand such a creation. 10 users It has to occupy 3G of memory,
so the back-end development must not findAll (don’t write it yourself, and don’t call it)
to write code in the future, and the sql query must add limit (it doesn’t work if there are conditions, the conditions may fail)

These errors cannot be detected in the test environment. Only in the production environment can there be millions of data, and the problems will be exposed.

Therefore, after the project is completed, it is also necessary to do a stress test. The interview will ask

  • 3) Memory overflow caused by dynamically generated classes
    • Reference day03.TestOomTooManyClass
      insert image description here
      insert image description here

5. Class loading

Require

  • Mastering the Classloading Phase
  • Mastering Class Loaders
  • Understanding the Parental Delegation Mechanism

Three Phases of the Class Loading Process

  1. load

    1. Load the bytecode of the class into the method area and create a class.class object
    2. If the parent class of this class is not loaded, load the parent class first
    3. Loading is performed lazily (only loaded when this class is really used)

类.class对象There are a series of reflection methods in it, which can know all the information of the class: which members are there, and which methods
类.class对象are stored in the heap

  1. Link

    1. Verification – verify whether the class conforms to the Class specification, legality, security check
    2. Preparation – allocate space for static variables and set default values ​​(but manually written assignment statement will not be executed at this time, it will be executed in the initialization phase, here is actually just to allocate space for static variables (final variables are exceptions, will be executed at this time) assignment))
    3. resolve – resolve symbolic references to constant pools into direct references
  2. initialization

    1. Static code blocks, static modified variable assignments, and static final modified reference type variable assignments will be combined into one <cinit>method, which will be called during initialization
    2. The basic type variable assignment modified by static final is completed in the linking stage
    3. Initialization is lazy execution (lazy execution will be initialized when the class is really used, and it will be divided into zeros, how good)

means of verification

  • Use jps to view the process number
  • Use jhsdb to debug, execute the command jhsdb.exe hsdbto open its graphical interface
    • Class Browser can view which classes are loaded in the current jvm
    • Console universe command to view the heap memory range
    • Use the console's g1regiondetails command to view region details
    • scanoops 起始地址 结束地址 对象类型You can find the object address in a range according to the type
    • The command of the console inspect 地址can view the details of the object corresponding to this address
  • Use the javap command to view the class bytecode

code description

  • day03.loader.TestLazy - verify that the loading of the class is lazy, and the class loading is triggered when it is used
  • day03.loader.TestFinal - Verify that final variables do not trigger class loading

The bytecode object is indeed in the heap space (eden area), not in the method area

insert image description here
insert image description here

insert image description here
insert image description here

  • Class initialization methods (static members (non-final common types) and static code blocks)

The static members and the statements in the static code block will be integrated into a method (cinit method), which is called when the class is initialized. Note
: variables of final static non-reference type are loaded when the class is loaded (create bytecode Object) will be initialized, there is no need to integrate here

insert image description here

  • Non-reference type variables decorated with final will not trigger class loading

The first two print statements seem to use classes. Student.c and Student.m do not actually use classes, so classes are not loaded at this time, and there are no classes in memory, which fully proves that class loading is Lazy loading
At this point, the class loading is complete, and you can see the bytecode information of the class (class structure: which members, which methods)

insert image description here
When a class A uses the final static ordinary type variable of another class B, which is actually a constant , at this time, class A directly copies the constant of class B to its own class, and will not really use another class B at all.

If the value of the constant is relatively small, then directly write it in the method. If the value is relatively large and exceeds the maximum range of short (>32767), it will be placed in the constant pool, and it will be fine
to get it from the constant pool when it is needed.
That is: the larger the value, it will be copied to class A's own constant pool, each class has its own constant pool (a constant list, and 1, 2, 3, ... numbered each constant, Give the number, go directly to the constant pool to get the value of that constant)

insert image description here

Analysis: symbol reference-"direct reference is a process that continues with the execution of the code, and it cannot be completed at one time. The
references to the static member variables of the class are all placed in the
constant pool. There are no direct references, only symbolic references (null pointers only know what type to point to, but there is no real memory)

Classloader for jdk 8

name which class to load illustrate
Bootstrap ClassLoader JAVA_HOME/jre/lib no direct access
Extension ClassLoader JAVA_HOME/jre/lib/ext The parent is Bootstrap, displaying null
Application ClassLoader classpath The superior is Extension
custom class loader customize The superior is Application

Class loaders like String.class, Application, and Extension are not in the class loader and cannot be loaded. At this time, you must ask Bootstrap to start the class loader to load it, and then the lower level can see it (String type is jdk, and the upper level needs to use it. Everything is visible and reasonable)
Like the class Student.class written by myself, it will also follow the rules and ask upwards step by step. The upper layer loader does not have this class, and the Application class loader is qualified to load Student.class and load it. (The upper class loader is not visible and does not need to be visible, this kind of shielding is very reasonable)

Parental Delegation Mechanism

The so-called parental delegation refers to the priority delegation of the upper-level class loader to load, if the upper-level class loader

  • This class can be found and loaded by the upper level. After loading, the class is also visible to the lower level loader
  • If this class cannot be found, the lower-level class loader is eligible to perform the loading

The purpose of parental delegation is twofold

  1. Let the classes in the upper-level class loader be shared with the lower-level (and vice versa), which means that your classes can rely on the core classes provided by jdk (and vice versa: jdk definitely does not need to rely on the classes you write yourself)

  2. Let the loading of classes have a priority order to ensure that core classes are loaded first

Classes in the upper class loader are visible to the lower class
, but classes in the lower class loader are not visible to the upper class

Misconceptions about parental delegation

The answers to the following interview questions are incorrect

insert image description here

What's wrong?

  • Can I load a fake java.lang.System by writing a class loader myself? The answer is no.

  • Assuming that your own class loader uses parent delegation , then the real java.lang.System will be loaded by the startup class loader first, and the fake one will not be loaded naturally.

  • Assuming that your own class loader does not use parental delegation , then when your class loader loads the fake java.lang.System, it needs to load the parent class java.lang.Object first, but you do not use delegation and cannot find java. lang.Object so loading will fail

  • The above are just assumptions . In fact, you will find that when the custom class loader loads a class starting with java., it will throw a security exception. In versions above jdk9, these special package names are bound to the module, and even the compilation cannot pass ( In actual operation, a security exception is thrown directly, or the compilation fails, and the hypothetical step is not reached, jdk has already taken security measures to prevent you from doing this, and you are not allowed to rewrite the java.lang package name)

code description

  • day03.loader.TestJdk9ClassLoader - Demonstration of the binding relationship between the class loader and the module = "Conclusion: Do not rewrite the package name and class name that jdk already has

6. Four kinds of references

Require

  • Master the Four Quotations

strong reference

  1. Ordinary variable assignment is a strong reference, such as A a = new A();

  2. Through the reference chain of GC Root, if the object cannot be strongly referenced, the object can be recycled

insert image description here

Soft Reference (SoftReference)

  1. For example: SoftReference a = new SoftReference(new A()); (There is a SoftReference object in the middle for transit, and a is indirectly associated with the object new A())

  2. If there is only a soft reference to the object, the first garbage collection will not reclaim the object. If the memory is still insufficient, the object will be released when it is recycled again (the GC will be triggered when the memory is insufficient, the first time I will spare you, and the second time the memory is insufficient The GC is triggered again, and the soft reference object will be recycled (the object pointed to by the strong reference cannot be recycled by GC))

  3. The soft reference itself needs to be released in conjunction with the reference queue (as shown in the figure below, object a is a soft reference, but the SoftReference itself is still a strong reference, and the GC cannot recycle the soft reference itself)

  4. A typical example is reflection data (data obtained through reflection are all soft reference data, such as: class name.class= "obtained member variables, methods and other data information are all soft references)

insert image description here

Weak reference (WeakReference)

  1. 例如:WeakReference a = new WeakReference(new A());

  2. If only weak references refer to the object, the object will be freed whenever garbage collection occurs

  3. The weak reference itself needs to be released with the reference queue (same as above)

  4. A typical example is the Entry object in ThreadLocalMap

insert image description here

Phantom Reference (PhantomReference)

  1. 例如: PhantomReference a = new PhantomReference(new A(), referenceQueue);

  2. It must be used together with the reference queue . When the object referenced by the virtual reference is recycled, the Reference Handler thread will enqueue the virtual reference object, so that you can know which objects are recycled, and further process their associated resources.

  3. A typical example is that Cleaner releases the direct memory associated with DirectByteBuffer

insert image description here

Detailed reference queue: as shown in the figure, after the objects a and b associated with the virtual reference are released, the virtual reference itself will be placed in the reference queue, and the Reference Handler thread is responsible for reclaiming them, because they may also be associated with some other resources ( Not just a object and b object)

code description

  • day03.reference.TestPhantomReference - Demonstrates basic usage of phantom references
  • day03.reference.TestWeakReference - Simulate ThreadLocalMap, use reference queue to release entry memory
String str = new String("hello"); // "hello"在堆内存中 (new出来的都在堆中)
String str = "hello"; // "hello" 在常量池中 

The Entry object in ThreadLocalMap, the key is a weak reference, and the value is a strong reference. The
insert image description here
above figure is a typical memory leak
solution: use a reference queue to associate an Entry with a reference queue. When the key of the Entry is recycled, the entire Entry The object will be put into the reference queue, and then directly remove the Map reference of the Entry object already in the reference queue (or check whether the current Entry is in the Map, and then record the corresponding reference of the Entry array in the Map set to null), there is no reference pointing to it, it will be recycled the next time it is recycled
jdk is not implemented in this way, and the cost will be relatively high

★★★The key is the ThreadLocal object itself. When the thread is running, it must be strongly referenced by other objects, so it is not afraid that it will be set as a weak reference. Before the thread ends, the key (with other strong references) will not be released. But once the value is set as a weak reference, there is really only this weak reference. It is very likely that the thread will be recycled by the GC before it ends. ★★★

7. finalize

Require

  • Master the working principle and disadvantages of finalize

finalize

  • General answer: It is a method in Object. If a subclass overrides it, this method will be called during garbage collection, and resources can be released and cleaned up in it.
  • Excellent answer: It is very bad to put resource release and cleanup in the finalize method, which will greatly affect performance, and even cause OOM (Out of Memory) in severe cases. It has been marked as @Deprecated since Java9 and is not recommended to be used.

Follow-up: Why is it very bad and affects performance?
See the principle below:

Supplement: Daemon thread, when the main thread has ended, the daemon thread will no longer execute (even if there is code that has not been executed)

finalize principle

  1. The core logic for processing the finalize method is located in the java.lang.ref.Finalizer class, which contains a static variable named unfinalized (doubly linked list structure), and Finalizer can also be regarded as another reference object (status and soft, Weak and imaginary, but not external, cannot be used directly)
  2. When the object of the finalize method is rewritten, when the construction method is called, the JVM will wrap it into a Finalizer object and add it to the unfinalized list (meaning that the finalize method of these objects has not been called yet, don’t release it easily (also What this reference chain does))

insert image description here

  1. There is another important static variable in the Finalizer class, that is, the ReferenceQueue reference queue (similar to the reference queue in the previous four references, which assists in releasing the reference object itself (helping in releasing some other associated resources). The difference is that the associated object is temporarily Cannot be recycled, because the finalize method must be called first) , it is empty at first. When the dog objects can be garbage collected, the Finalizer objects corresponding to these dog objects will be added to this reference queue
  2. But at this time, the Dog object cannot be recycled immediately, because the reference chain unfinalized -> Finalizer is still referencing it, in order to [don’t rush to recycle, wait until I finish adjusting the finalize method, and then recycle]
  3. The FinalizerThread thread will take each Finalizer object from the ReferenceQueue one by one, disconnect them from the linked list and actually call the finalize method

insert image description here

  1. Since the entire Finalizer object has been disconnected from the unfinalized linked list, no one can reference it and the dog object, so it will be recycled in the next gc

finalize disadvantages

  • Unable to guarantee resource release: FinalizerThread is a daemon thread, and the code may not be executed in time, and the thread will end
  • Unable to judge whether an error occurred: when the finalize method is executed, any exception will be swallowed (Throwable try-catch swallowed)
  • The memory is not released in time: when the object that rewrites the finalize method is gc for the first time, the memory it occupies cannot be released in time, because it has to wait for the FinalizerThread to call finalize, remove it from the unfinalized queue, and the second time Only when gc can actually release the memory
  • Some articles mentioned [Finalizer thread will compete with our main thread, but because it has a lower priority and gets less CPU time, it will never catch up with the pace of the main thread] This is obviously wrong, The priority of FinalizerThread is higher than that of ordinary threads (max-2=8, ordinary threads are only 5), the reason should be the combination of slow serial execution of finalize and other reasons (take one on the queue and call one finalize)

code description

  • day03.reference.TestFinalize - test code for finalize

insert image description here

Guess you like

Origin blog.csdn.net/hza419763578/article/details/130630961