- The location of the JVM
- The overall structure of the JVM
Class loading subsystem
Class loading process
- Load gets the binary byte stream that defines the Class through the fully qualified name of the Class, converts the static storage structure represented by the byte stream into the runtime data structure of the method area, and generates a Class object in memory to act as an access point for the various data of the method area
- link
- Validation ensures that the Class file byte stream is compliant with virtual machine requirements and does not compromise the JVM itself
- To prepare
给Class variablesAllocates memory and sets default initial values for class variables
static int a = 1; // prepare:a=0 ---> initial:a=1
Static variables that are final are excluded because memory is allocated at compile time and initialization is displayed during preparation
- parsing
Converting symbolic references in the constant pool to direct references is mostly done after initialization
When a normal Java class is loaded into memory, it also loads many classes, which are located by symbolic references
- Initialize the
Executes the class constructor method (), which the JavAC compiler automatically collects from classesAssignment actions for all class variables and statements in static code blocksconcomitantprivate static int num = 1; static{ num = 3; } 0 iconst_1 1 putstatic #3 <com/atguigu/java/ClassInitTest.num> 4 iconst_3 5 putstatic #3 <com/atguigu/java/ClassInitTest.num> 8 return Copy the code
If the class has a parent class, the JVM guarantees that the parent class’s () is executed before the subclass’s () is executed. The virtual machine ensures that the () methods of a class are locked synchronously in multiple threads (singleton – inner class methods, safe execution reasons)
- There are seven cases in which active use of a class results in initialization of the class
- Create an instance of the class
- Access or assign a value to a static variable of a class or interface
- Call a static method of a class
- Reflection calls
- Initialize a subclass of a class
- Classes that are identified as startup classes when the Java virtual machine starts
- Dynamic languages after JDK7
- There are seven cases in which active use of a class results in initialization of the class
Class loader
Class loaders are containment relationships, not inheritance relationships, more like hierarchies. Different class loaders load different classes, each doing its job
- BootStrapClassLoader starts the class loader
- Written in C/C++, nested within the JVM (no ClassLoader inheritance, no inheritance, C++ implementation)
- The core class library used to load Java
- Loads extension classes and application classloaders and specifies them as parent classloaders
- ExtClassLoader Extends the class loader
- Java language, is an inner class under the sun.misc.Launcher class
- Derived from the ClassLoader class, the parent ClassLoader is the boot ClassLoader
- Load the class libraries from the jre/lib/ext subdirectory (if a user-created Jar is placed in this directory, it will also be automatically loaded by the extension class loader)
- AppClassLoader System class loader
- Java language, is an inner class of Sun.misc.Launcher
- Derived from the ClassLoader class, the parent ClassLoader is the extension ClassLoader
- It is responsible for loading the class libraries under the path specified by the environment variable classpath or the system property java.class.path
- The ClassLoader can be obtained by using the getSystemClassLoader() method of the ClassLoader
- User-defined class loaders
- Why custom?
- Isolated loading classes (middleware and application are isolated, and the Jar packages of middleware and application conflict)
- Modify the way classes are loaded (when needed)
- Extended load sources (other bytecode sources, such as databases)
- Prevent source code leakage
- How to customize?
- Inherits the abstract java.lang.classloader class
- Before JDK1.2, loadClass() was overridden to implement custom class loading logic; Overwriting loadClass() is not recommended after JDK1.2, instead writing custom logic in findClass()
- If you don’t have overly complex requirements when writing a custom class loader, you can simply inherit the URLClassLoader class instead of having to write findClass() and how it gets the bytecode stream
- Why custom?
- Parent delegation mechanism
The Java virtual machine loads a class on demand, meaning that it is loaded into memory only when it is intended to be used. In addition, the parent delegate mode is adopted when loading the class, that is, the request is handed over to the parent class to handle, the specific workflow:- If a classloader receives a classload request, it does not load the request itself. Instead, it delegates the request to the parent class’s loader.
- If the parent class loader also has its parent class loader, then further delegate up, recursively, the request will eventually reach the top level of the start class loader;
- If the parent class loader can complete the task, it returns successfully. If the parent class loader cannot complete the task, the child loader will try to load itself. This is the parent delegate mode.
- Sandbox safety mechanism: Custom JDK core classes such as java.lang.String are loaded by the JVM using the boot class loader. Jar (Java \lang\String.class), error message indicating that there is no main method, because rt.jar (String) is loaded. This ensures the protection of the Java core source code
Runtime data area
PC register
- Function: Store the address pointing to the next instruction, which is executed by the execution engine reading the next instruction from the PC register
- Why use a PC register to record the execution address of the current thread? Because the CPU is constantly switching threads, it needs to know where to start when it switches back
- Why are PC registers set to be thread private? To accurately record the address of the current bytecode instructions being executed by each thread, a PC register is assigned to each thread so that the threads compute independently and do not interfere with each other
The virtual machine stack
- What is a virtual machine stack? Each thread synchronously creates a virtual stack when it is created. It holds stack frames internally, and each stack frame corresponds to a method call
- What does the virtual machine stack do? Manages the running of Java programs, saves local variables and partial results of methods, and participates in method calls and returns
- Possible exceptions on the VM stack
- If a fixed size virtual stack is used, a StackOverflowError is raised if thread requests are allocated more than the maximum allowed stack size
- An OutOfMemoryError is thrown if a dynamically extended virtual stack fails to allocate sufficient memory when attempting to extend
- Set stack size -xss256K -xss1m
- Stack data exists in the format of stack frames, which store:
- Local variable scale
- Is an array of numbers used to store method parameters and local variables defined in the method body
- The length (capacity) of the local variable table is determined at compile time and is not modified once determined
- Bytecode instruction
- Locally variable scale length
- Row number table mapping
- Local variable scale
- The basic storage unit for a local variable table is slot-variable Slot, in which types up to 32 bits occupy one Slot and 64 bits occupy two slots
- If the current frame is created by a constructor or instance method, the this pointer is placed in the first slot
- Slot duplication: If a local variable goes out of scope, new local variables applied after its scope are likely to reuse the slot of the expired layout variable, thereby saving resources.
- The operand stack
- Function: In the process of method execution, data is written or read to the stack according to the bytecode instructions, that is, the operation of the stack and the operation of the stack (the operation of the stack tube, the local variable table is equivalent to the raw material, and the operand stack is equivalent to the processing procedure)
- If the called method has a return value, the return value is pushed into the operand stack of the current stack frame and updates the NEXT bytecode instruction to be executed in the PC register
- Dynamic linking (method references to runtime constant pools)
- Each stack frame contains an internal reference to the method that the stack frame belongs to in the runtime constant pool. The purpose of including this reference is to enable dynamic linking in code that supports the current method
- When a Java source file is compiled into a bytecode file, all variable and method references are stored as symbolic references in the class file’s constant pool
- Method call instruction
- Invokestatic: Invokes static methods, and the parsing phase determines the unique method version
- Invokespecial: Call method, private and parent methods. The parsing phase determines the unique method version
- Invokevirtual: calls all virtual methods (subclasses call their parent’s final methods, which are invokevirtual, but are actually non-virtual)
- Invokeinterface: Invokes interface methods
- Invokedynamic: Dynamically resolves the method to be invoked and executes it
- Method return address (definition of method normal exit or abnormal exit)
- Some additional information
- Local variable scale
- Example stack overflow? StackOverflowError -xss allows you to set the stack size
- Can you guarantee no overflows by adjusting the stack size? No, it can be divided into two cases:
- Assuming that the original stack space can be pushed 5000 times, the program will report the SOF error if it wants to be pushed 6000 times, but it can adjust the stack size so that it can be pushed 7000 times and no error will be reported
- The original program is a recursive loop, will keep pushing the stack, so no adjustment will help
- Is it better to allocate more stack memory? It doesn’t theoretically reduce the probability of SOF occurring, but the total memory space is limited, and the rest of the space is small
- Does garbage collection involve the virtual machine stack? No virtual stack Error, but no GC, its garbage collection -> out of the stack form
- Are local variables defined in a method thread-safe? Specifically, if a variable dies inside a method, it is thread-safe; If the variable is passed, or escapes (the scope is not just internal), it is not thread-safe
Local method stack
- The local method stack is similar to the virtual machine stack except that it is used to manage calls to local methods, whereas the virtual machine stack manages calls to Java methods
- When a thread calls a local method, it is no longer bound by the virtual machine and has the same privileges as the virtual machine (access to the runtime data area inside the virtual machine through the local method interface; Allocate any amount of memory from the local memory heap.
- What are the local methods? A native modification method is a Java interface that calls non-Java code. Its function is to integrate different programming languages. When defining a native method, no implementation body is provided
The heap
- Important concepts related to heap
- There is only one heap memory per JVM instance, and starting two Java processes requires two heap memory
- The Java heap area is created at JVM startup, and its space is determined at this point
- The heap can be in a physically discontinuous memory space, but logically should be considered contiguous
- All threads share the Java heap, which can also be partitioned into a thread private buffer TLAB.
- The relation between heap, stack and method area: the stack frame of the stack stores the object reference, which points to the object’s position in the heap, and the information of the object’s class and method are stored in the method area
- Objects in the heap are not removed immediately after the method ends, but only during garbage collection
- Heap space is a key area for garbage collection
- Heap memory segmentation
- JDK7 and previous heap memory is logically divided into three parts: new generation, old generation, and permanent generation
- JDK8 and later heap memory is logically divided into three parts: new generation, old age, and meta space
- Heap size Settings and viewing (heap size Settings only include new generation and old generation)
- -xms is used to indicate the starting memory of the heap, such as -xms6m, -xMS1024K (equal to Eden + the size of one survivor, the other survivor does not hold objects due to garbage collection)
- -xmx is used to indicate the maximum memory of the heap (usually the start and maximum memory are set to the same number, so that the calculation of the heap size does not need to be reallocated after the garbage collection mechanism has cleaned up the heap, improving performance)
- Default heap size: initial memory size = physical memory size /64, maximum memory size = physical memory size /4
- View the set parameters:
- JPS + jstat -GC process ID
- -XX:+PrintGCDetails
- New generation and old age
- -xx :newRatio=x The default value is 2, that is, new generation: old age = 1:2
- -xx :SurvivorRatio=x default 8, i.e. Eden zone, Survivor zone = 8:1:1 (default 8, but actual 6:1:1 due to adaptive memory allocation policy)
- -Xmn: Sets the space size of the new generation
- Object allocation procedure
- The object of new will be placed in Eden first. When Eden is full and the program is creating objects, the JVM will initiate a Minor GC To destroy the objects that are no longer referenced in Eden and move the referenced objects To a To Survivor zone (marking the object age as 1).
2. The program continues To run. If garbage collection is triggered again, the surviving objects in Eden zone will be placed in To Survivor zone, and the surviving objects in From Survivor zone will be checked. If the surviving objects are moved To To Survivor zone (object age +1)3. If garbage collection is triggered again, proceed with Step 1/2. If the age of the Survivor reaches 15, the Survivor will be promoted to the old age by defaultX. Other special circumstances
When do objects enter the old age?
The age of the object reaches the threshold. If the age of the surviving object reaches the threshold when the Eden area and Survivor area copy the surviving object, the object will be promoted to the old age. In Survivor zone, if the sum of all objects of the same age is greater than half of Survivor zone, then the objects of the age greater than or equal to this age will be promoted to the old age 4. After a Minor GC, there are too many surviving objects to fit into a survivor region, and they are placed into the old ageCopy the code
- The GC classification
- Part collection:
- Minor GC/Young GC: Only garbage collection for the new generation (Eden\S0,S1) (note: no GARBAGE collection for S0, incidental collection for Eden area)
- Major GC (Old GC): Just Old GC
- Mixed GC: Collects garbage from the entire Cenozoic generation and parts of the old generation (because G1 breaks Cenozoic and old generation together)
- Full GC: Collects the entire Java heap and method area garbage collection
Trigger time:
When system.gc () is called, full GC is recommended, but is not a necessary event. 2. Insufficient old age space 3. Insufficient method area space 4. The average size of old age after Minor GC is greater than the available memory of old age 5. When Eden is copied from Survivor region to another Survivor region, the size of the object is larger than its available memory. When the object is migrated to the old age, it is found that the old age cannot be saved, and full GC occursCopy the code
- Part collection:
p83-p86
Methods area
- Method area related important concepts
- The method area, like the heap, is an area of memory shared by threads (multiple threads trying to initialize a class can only be initialized by one thread, putting class structures and methods into the method area).
- The method area is created at virtual machine startup, and its actual physical memory space is as discontinuous as the Java heap area
- The method area size is the same as the heap space, and can be fixed size or extensible
- The size of the method area determines how many classes the system can hold. If the system defines too many classes and causes the method area to overflow, the VIRTUAL machine will also throw an overflow error
- In JDK7 and before, it is customary to call a method area a permanent generation; In JDK8 and later, metspaces are used instead of permanent generations (metspaces use local memory, whereas permanent generations use memory set up in the virtual machine)
- Sets the parameters for the method area size
- -xx :PermSize= Sets the initial space allocated for the permanent generation. The default space is 20.75 MB
- -xx :MaxPermSize= Sets the maximum space that can be allocated for the permanent generation. The default value is 64 MB for 32-bit machines and 82 MB for 64-bit machines
- After JDK8, PermSize is replaced with MetaspaceSize due to the change in method area structure
- The internal structure of the method area
- The type information
- For each loaded type (class, interface, enumeration, annotation), the JVM must store the following type information in the method area: the full pathname, the full valid name of the immediate parent class, the type modifier, and an ordered list of the immediate interfaces
- Domain information (Properties)
- The JVM must keep information about all fields of the type and the order in which the fields are declared in the method area
- Domain name, domain type, and domain modifier
- Methods information
- The JVM must keep information about all methods and the order in which they are declared
- Method name, method return type, number and type of method parameters, method modifiers, method bytecode, operand stack, local variable table, exception table
- Run-time constant pool
- Why do I need constant pools (in class files)?
- Java is an object-oriented programming language, a simple application needs to load a considerable number of classes, if these classes are placed in a class file is very large, and there is some repeated data like strings there is no need to repeat the definition; So with the help of constant pool, constant pool is stored in symbol references, only when it is loaded into memory, these symbol references will become direct references (constant pool is like RGB three primary colors, when you need any color can be removed from the three primary colors to match their colors)
- What is a constant pool? Constant pool It is part of the Class file and can be viewed as a table through which virtual machine instructions find the Class names, method names, parameter types, literals, and so on to execute
- What is the runtime constant pool?
- The runtime constant pool is part of the method area, which is called the runtime constant pool after the class is loaded and entered into the method area in the run data area.
- The runtime constant pool contains a variety of constants, from numeric literals that are explicit at compile time to field references that are resolved at run time (unlike symbolic addresses in the constant pool, which are translated to real addresses). It is dynamic compared to a constant pool (e.g. String.intern())
- Why do I need constant pools (in class files)?
- The type information
- The evolution details of the method area
- JDK1.6 and before: there are permanent generations on which static variables are stored
- JDK1.7: permanent generation exists, but has been phased out, where the string constant pool, static variables are removed from the permanent generation and stored in the heap
- JDK1.8 and later: No persistent generation, type information, fields, methods, constants are stored in local memory meta-space, but the string constant pool, static variables are still stored in the heap
What will be removed from the permanent generation after JDK8?
1. The space size of the permanent generation is difficult to determine. Full GC occurs when the setup space is small, where STW operations affect the efficiency of the user thread (OOM if most of the loaded classes are still used). Setting up too much space, space is wasted. The meta space uses local memory and is not limited by VM space. 2. It is difficult to tune the permanent generation. full gcCopy the code
Why should the storage location of StringTable be changed? In JDK7 and later, put the string constant pool into the heap space. Because permanent generation collection is inefficient, it is only triggered during full GC, which is only triggered when old generations or permanent generation space is running out. As a result, StringTable is not efficient in collecting strings, and there are a large number of strings created during development. In this case, the string collection efficiency is very low, which further causes the persistent generation memory to run out
- Method area garbage collection
- The method area garbage collection consists of two main parts: obsolete constants in the constant pool and no longer used types
Object instantiated memory layout and access location
- Instantiation of an object
- How objects are created
- new
- Class newInstance(): constructor that can only call empty arguments. Permission must be public
- In JDK9, you can call empty and parameter constructors without permission requirements
- Using Clone (): No constructor is called, and the current class implements the Cloneable interface
- Use deserialization: Retrieve a binary stream of an object from a file, network, and then restore it to an object
- The third-party library Objecnesis
- Steps for object creation
- Judge whether the corresponding object class has been loaded into memory, if there is no load to call class loader to load the corresponding class (virtual opportunities to the new command, the first check the parameters of this instruction can position in the constant pool of yuan space into a symbolic reference, and check whether the notation to refer to the class of the representative has been loaded, parsed and initialization. If not, in parent delegate mode, use the current classloader to find the corresponding. Class file. If no file is found, throw ClassNotFoundException, if found, class load and generate the corresponding class object.)
- Allocates memory for objects. First, the size of the object is calculated, and then a chunk of the heap is allocated to the new object. If the instance member variable is a reference variable, only the reference variable space is allocated (4 bytes). If memory is neat, use pointer collisions, if memory is not neat, use the free list method
- Handle concurrency security issues. CAS failed to retry, region locking to ensure atomicity of update; Pre-allocate a TLAB for each thread
- Initialize allocation to space. Default values are set for all properties, ensuring that object instance fields can be used without assignment
Order of assignment: default initialization – explicit initialization/initialization in code block – initialization in constructor
- Sets the object header of the object.
- Execute method to initialize (the last two attribute assignments are done here)
- How objects are created
- The internal layout of the object
- Object head
- Runtime metadata
- Hash value
- GC generational age
- Lock status flag
- The lock held by the thread
- Biased thread ID
- Bias timestamp
- Type a pointer
- Point to the class metadata InstanceClass to determine the type to which the object belongs
- Runtime metadata
- The instance data
- Object actually stores valid information, including the various types of fields defined in program code (both inherited and owned)
Rule: Fields of the same width are always assigned together; Variables defined in a parent class appear before subclasses; If the CompactFields parameter is true, the subclass’s pickings may be inserted into the parent variable
- Alignment filling
- Placeholder function
- The instance
public class CustomerTest { public static void main(String[] args) { Customer cust = newCustomer(); }}public class Customer{ int id = 1001; String name; Account acct; { name = Anonymous Client; } public Customer(a){ acct = newAccount(); }}class Account{}Copy the code
- Object head
- Object access location
- Problem solved: How to access an object instance inside a stack frame via an object reference inside it (on-stack reference)
- classification
- Handle access
- Principle: in the heap handle to open up an area to deposit pool, handle the pool to deposit a lot of handle, an object corresponds to a handle, a handle has two Pointers: pointer to the object instance data (he instance of heap space) and the types of data pointer to the object (he points to the method of object type)
- Advantages: References maintained in stack space are very stable. If objects are moved in heap space, only a pointer in the handle needs to be changed, and no stack reference needs to be changed
- Disadvantages: Object reference must first find the corresponding handle in the handle pool, and then find the instance and instance type from the handle clause. Moreover, the handle pool space should be opened separately, which is inefficient
- Direct Pointers (adopted by Hotspot)
- Stack space references refer directly to object instances in the heap, where there are type Pointers to object types in the method area
- Advantages: Higher efficiency than handle access
- Handle access
Direct memory
- Important theory
- It is not part of the run-time data area of the virtual machine, nor is it an area of memory defined in the virtual machine specification.
- The amount of memory that is directly requested from the system outside the Java heap (the amount of memory that a Java process occupies can be interpreted as heap + direct memory)
- Derived from NIO, Native memory is operated by DirectByteBuffer that exists in the heap
- In general, direct memory is faster to access than the Java heap (consider direct memory for frequent reads and writes; Java’s NIO library allows Java programs to use direct memory for data buffers.)
- Direct buffer memory (because Direct memory is outside the Java heap, it is possible for Direct memory to appear in OOM if the maximum heap executed by -xmx is close to the maximum memory of the operating system)
- Disadvantages: High cost of distribution recovery; It is not managed by JVM memory reclamation
- The direct memory size can be set directly with MaxDirectMemorySize (if not specified, it defaults to the maximum heap size -Xmx parameter value)
Execution engine
- Execution classification of Java code
- The source code is compiled into a bytecode file, which is then converted to machine code for execution at run time through the interpreter
- Compilation execution, directly compiled into machine code. Methods are compiled to machine code by the just-in-time compiler before execution
- The interpreter and JIT compiler have their own pros and cons
- The interpreter responds quickly. When the program starts, the interpreter gets the bytecode and immediately interprets it line by line with the help of a PC counter. The JIT needs to compile into machine instructions and then execute them
- JIT compilers perform efficiently. It compiles bytecode into machine instructions, which can be executed repeatedly. Hot code execution is efficient
String splicing
- String stitching summary of interview questions
- Concatenation of constants to constants results in the constant pool, and the principle is compile-time optimization
- Constants of the same content are not stored in the constant pool
- As long as one of the concatenation operations is a variable, it is stored in the heap. The principle of concatenation of variables is StringBuilder (final String s = “1”, not counting variables, there is compile-time optimization).
- If the result of the concatenation calls intern(), it actively puts string objects that are not already in the constant pool into the pool and returns the object’s address
- Intern method
- Check whether the string value exists in the string constant pool (using equals internally), if so, return the address of the string in the constant pool; If the string constant pool does not exist, a copy is loaded in the constant pool and the address of the object is returned.
- Before JDK1.6, if the string constant pool does not exist, a copy of the object is made, put it into the string constant pool, and return the address of the object in the string constant pool. In JDK1.7 and later, if the string constant pool is not present, a copy of the object’s reference address is made, put into the pool, and the reference address from the string pool is returned
- How do I guarantee that the variable S refers to the data in the string constant pool?
- String s = “shkstart”; // The way literals are defined
- Call the intern ()
String s = new String("shkstart").intern(); String s = new StringBuilder("shkstart").toString().intern(); Copy the code
- How many objects will new String(“ab”) create?
- Two objects, one created in heap space by the new keyword and one in the string constant pool
- How many objects does new String(“a”) + new String(“b”) create?
- String(“x”) creates a String object of type String
- This operation does not generate the object “ab” in the string constant pool
- Intern ()?
String s = new String("1");// s points to string object 1 created in the heap
s.intern();// Before calling this method, "1" already exists in the string constant pool, so this operation does not have any effect
String s2 = "1";// s2 takes 1 in the string constant pool
System.out.println(s == s2);//jdk6: false jdk7/8: false one is in the heap space, and one is in the constant pool
String s3 = new String("1") + new String("1");//s3 variable record address: new String("11") and String constant pool does not exist "11"
s3.intern();Generate "11" in the string constant pool.
// jdk6: Since the string constant pool is in the permanent generation, a new object "11" must be created with its new address in the permanent generation. Jdk7: in order to save space, we do not create "11" in the constant pool, but copy the address of the existing "11" object in the heap into the constant pool
String s4 = "11";// address of the s4 variable record: use the address of "11" generated in the constant pool when the previous line of code was executed
System.out.println(s3 == s4);//jdk6: false jdk7/8: true
Copy the code