1. The execution process of the java program
java source file -> parser -> class file -> java class loader -> java runtime data area -> execution engine
2. Let's take a look at the java runtime data area next
It includes program counter, virtual machine stack, local method stack, method area, and heap. Among them, program counter, virtual machine stack, local method area belong to instructions, and method area and heap belong to data.
1. Program counter
It is used to indicate which instruction the program executes, which is logically the same as the function of the program counter in assembly language. The JVM specification stipulates that if the thread executes a non-native method, the program counter points to the address and line number of the bytecode instruction being executed by the current thread. If the thread executes the native method, the value in the program counter is undefined. Each thread has its own independent program counter. why? Because under multi-threading, a CPU core can only execute instructions in one thread at a time, so in order to enable each thread to resume the execution of the program before the switch after thread switching, each thread has its own independent program. counter.
2. Java Virtual Machine Stack ( VM Stack )
The Java virtual machine stack stores stack frames one by one. The stack is a data structure, and the data structure is used to store data, so the virtual machine stack is also used to store data. Stores the data, instructions and return addresses required by the current thread running method. When a program executes a method, it creates a stack frame and pushes it onto the stack. After execution, the stack is removed from the stack frame. The virtual machine stack has: local variable table, operand stack, dynamic link, method exit.
Local variable table:
The table that stores local variables, the basic data types of java ( boolean, byte, char, short, int, float, long, double ), the reference of the object (reference type, it is not equivalent to the object itself, it may be a pointer to the object The reference pointer of the starting address, or it may point to a handle representing the object or other location related to this object) and returnAddress type (pointing to the address of a bytecode instruction), where 64-bit long and double type data It will occupy 2 local variable spaces (Slot), and the rest of the data types only occupy 1. The size of the local variable table is determined by the compiler, so the size of the local variable table does not change during program execution. In the Java virtual machine specification, two exception conditions are specified for this area: if the stack depth requested by the thread is greater than the depth allowed by the virtual machine, a StackOverflowError exception will be thrown; if the virtual machine stack can be dynamically expanded (most current Java Virtual machines can be dynamically expanded, but the Java virtual machine specification also allows a fixed-length virtual machine stack). If enough memory cannot be applied for during expansion, an OutOfMemoryError exception will be thrown.
Operand stack:
The virtual machine uses the operand stack as its work area. All calculations in the program are done with the help of the operand stack. Most instructions pop data from here, perform the operation, and then push the result back to the operand. stack.
JVM将内存划分为6个部分:PC寄存器(也叫程序计数器)、虚拟机栈、堆、方法区、运行时常量池、本地方法栈
-
PC寄存器(程序计数器):用于记录当前线程运行时的位置,每一个线程都有一个独立的程序计数器,线程的阻塞、恢复、挂起等一系列操作都需要程序计数器的参与,因此必须是线程私有的。
-
java 虚拟机栈:在创建线程时创建的,用来存储栈帧,因此也是线程私有的。java程序中的方法在执行时,会创建一个栈帧,用于存储方法运行时的临时数据和中间结果,包括局部变量表、操作数栈、动态链接、方法出口等信息。这些栈帧就存储在栈中。如果栈深度大于虚拟机允许的最大深度,则抛出StackOverflowError异常。
- 局部变量表:方法的局部变量列表,在编译时就写入了class文件
- 操作数栈:int x = 1; 就需要将 1 压入操作数栈,再将 1 赋值给变量x
-
java堆:java堆被所有线程共享,堆的主要作用就是存储对象。如果堆空间不够,但扩展时又不能申请到足够的内存时,则抛出OutOfMemoryError异常。
-
方法区:方发区被各个线程共享,用于存储静态变量、运行时常量池等信息。
- 本地方法栈:本地方法栈的主要作用就是支持native方法,比如在java中调用C/C++
六、垃圾回收机制:
(2)、可达性分析
设立若干根对象(GC Root),每个对象都是一个子节点,当一个对象找不到根时,就认为该对象不可达。
3、怎么回收?
- 标记——清除算法
- 复制算法
- 分代算法
(1)、标记——清除算法
遍历所有的GC Root,分别标记处可达的对象和不可达的对象,然后将不可达的对象回收。
缺点是:效率低、回收得到的空间不连续
(2)、复制算法
将内存分为两块,每次只使用一块。当这一块内存满了,就将还存活的对象复制到另一块上,并且严格按照内存地址排列,然后把已使用的那块内存统一回 收。
优点是:能够得到连续的内存空间
缺点是:浪费了一半内存
(3)、分代算法
在java中,把内存中的对象按生命长短分为:
- 新生代:活不了多久就go die 了,比如局部变量
- 老年代:老不死的,活的久但也会go die,比如一些生命周期长的对象
- 永久代:千年王八万年龟,不死,比如加载的class信息
- 有一点需要注意:新生代和老年代存储在java虚拟机堆上 ;永久代存储在方法区上
补充:java finalize()方法:
在被GC回收前,可以做一些操作,比如释放资源。有点像析构函数,但是一个对象只能调用一次finalize()方法。