2.3 Java虚拟机栈,压栈帧 执行方法的操作过程
3、垃圾回收机制和垃圾回收算法
3.1、垃圾回收机制
3.2、垃圾回收算法
3.2.1、标记-清除
3.2.2、标记-复制
3.2.3、标记-整理
基于咕泡学院Jack老师视频
相关视频:https://ke.qq.com/course/466802?taid=3966307809042290
主要内容:
1、什么是运行时数据区;
2、运行时数据区为什么要这么划分;
3、方法的执行和Java虚拟机栈详解;
4、垃圾回收机制和垃圾回收算法;
1、准备工作
======
Person.java文件
class Person {
private String name = “Jack”;
private int age;
private final double salary = 100;
private static String address;
private final static String hobby = “Programming”;
// private Object obj = new Object();
public void say() {
System.out.println(“Person say…”);
}
public static int calc(int op1, int op2) {
op1 = 3;
int result = op1 + op2;
// Object o = obj;
return result;
}
public static void main(String[] args) {
System.out.println(calc(1,2));
}
}
通过javac命令生成class文件
文件位置:
2、运行时数据区
========
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5
Java8 运行时数据区官方文档。
2.1、什么是运行时数据区
2.2、运行时数据区可以划分为几个区域?为什么要这么划分?
class文件中到底有多少数据类型?
对象,常量,静态变量,普通的成员变量,方法,局部变量,父类 …
Java官方文档可以看到以下目录:
-
2.5.1. The pc Register
-
2.5.2. Java Virtual Machine Stacks
-
2.5.3. Heap: 对象【普通的成员变量】,数组 --》堆 new Person(); new Student(); Class clazz;
-
2.5.4. Method Area:类的信息【创建的时间,元数据信息】、常量、静态变量、即时编译器编译之后的代码
-
2.5.5. Run-Time Constant Pool
-
2.5.6. Native Method Stacks
Heap:堆
其实就是存储Java对象的。
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
Java虚拟机具有一个在所有Java虚拟机线程之间共享的_堆_。堆是运行时数据区,从中分配了所有类实例和数组的内存。
private int age; ----> 普通变量【普通的成员变量】存储在哪里?
如果我要调用普通变量,是不是要先创建对象.age —> 随着对象存储在堆内存。
Java虚拟机具有一个在所有Java虚拟机线程之间共享的_堆_。堆是运行时数据区,从中分配了所有类实例和数组的内存。
堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为_垃圾收集器_)回收;对象永远不会显式释放。Java虚拟机不假定特定类型的自动存储管理系统,可以根据实现者的系统要求选择存储管理技术。堆的大小可以是固定的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以将其收缩。堆的内存不必是连续的。
Java虚拟机实现可以为程序员或用户提供对堆的初始大小的控制,并且,如果可以动态扩展或收缩堆,则可以控制最大和最小堆大小。
Method Area:方法区
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the “text” segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.
Java虚拟机具有在所有Java虚拟机线程之间共享的_方法区域_。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法(第2.9节)。
Java虚拟机具有在所有Java虚拟机线程之间共享的_方法区域_。该方法区域类似于常规语言的编译代码的存储区域,或者类似于操作系统过程中的“文本”段。它存储每个类的结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码,包括用于类和实例初始化以及接口初始化的特殊方法(第2.9节)。
方法区域是在虚拟机启动时创建的。尽管方法区域在逻辑上是堆的一部分,但是简单的实现可以选择不进行垃圾回收或压缩。该规范没有规定方法区域的位置或用于管理已编译代码的策略。方法区域可以是固定大小的,或者可以根据计算的需要进行扩展,如果不需要更大的方法区域,则可以缩小。方法区域的内存不必是连续的。
Java虚拟机实现可以为程序员或用户提供对方法区域初始大小的控制,以及在方法区域大小可变的情况下,可以控制最大和最小方法区域大小。
Heap和Method Area总结:
1、is shared among all java Virtual Machine threads. —>所有线程所共享的区域–>这两块数据中的数据是线程非安全的,因为可能会被多个线程用到同一个数据。
2、The heap is created on virtual machine start-up. The method area is created on virtual machine start-up. —> Heap和Method Area的创建是跟虚拟机进程相关的。
3、If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an OutOfMemoryError
. If memory in the method area cannot be made available to satisfy an allocation request, the Java Virtual Machine throws an OutOfMemoryError
. —> Heap和Method Area的大小可以通过JVM参数来控制,当他们的内存大小不够用的时候,就会抛出 OutOfMemoryError.
Java程序启动的话,会有一个Java进程,Java程序的灵魂应该就是线程的执行。(另一个是面向对象)。
Java Virtual Machine Stacks:Java虚拟机堆栈
方法的执行一定是由线程来执行的。
T1 T2 T3 T4 线程执行方法的过程应该可以用一个数据结构表示:栈 --> 先进后出。
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.
每个Java虚拟机线程都有一个私有_Java虚拟机堆栈_,与该线程同时创建。
每个Java虚拟机线程都有一个私有_Java虚拟机堆栈_,与该线程同时创建。Java虚拟机堆栈存储框架(第2.6节)。Java虚拟机堆栈类似于C之类的常规语言的堆栈:它保存局部变量和部分结果,并在方法调用和返回中起作用。因为除了推送和弹出帧外,从不直接操纵Java虚拟机堆栈,所以可以为堆分配帧。Java虚拟机堆栈的内存不必是连续的。
在第一版_中的Java ®虚拟机规范,Java虚拟机堆被称为_Java堆栈_。_
该规范允许Java虚拟机堆栈具有固定大小,或者根据计算要求动态扩展和收缩。如果Java虚拟机堆栈的大小固定,则在创建每个Java虚拟机堆栈时可以独立选择它们的大小。
Java虚拟机实现可以为程序员或用户提供对Java虚拟机堆栈的初始大小的控制,并且在动态扩展或收缩Java虚拟机堆栈的情况下,可以控制最大和最小大小。
Native Method Stacks:本地方法堆栈
other than the Java programming language). Native method stacks may also be used by the implementation of an interpreter for the Java Virtual Machine’s instruction set in a language such as C. Java Virtual Machine implementations that cannot load
native
methods and that do not themselves rely on conventional stacks need not supply native method stacks. If supplied, native method stacks are typically allocated per thread when each thread is created.
This specification permits native method stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the native method stacks are of a fixed size, the size of each native method stack may be chosen independently when that stack is created.
A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the native method stacks, as well as, in the case of varying-size native method stacks, control over the maximum and minimum method stack sizes.
The following exceptional conditions are associated with native method stacks:
- If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an
OutOfMemoryError
.
从修饰词Native就可以看出,这个栈是存储C语言方法的地方。
Java虚拟机的实现可以使用俗称“ C堆栈”的常规堆栈来支持
native
方法(以Java编程语言以外的其他语言编写的方法)。解释程序的实现也可以使用诸如C之类的语言来解释Java虚拟机的指令集,以使用native
本机方法栈。无法加载方法并且自身不依赖于常规堆栈的Java虚拟机实现不需要提供本机方法栈。如果提供,通常在创建每个线程时为每个线程分配本机方法堆栈。
该规范允许本机方法堆栈具有固定大小,或者根据计算要求动态扩展和收缩。如果本机方法堆栈的大小固定,则在创建每个本机方法堆栈的大小时可以独立选择。
Java虚拟机实现可以为程序员或用户提供对本机方法堆栈的初始大小的控制,以及在本机方法堆栈大小变化的情况下,对最大和最小方法堆栈大小的控制。
以下异常条件与本机方法堆栈相关联:
- 如果线程中的计算需要比允许的更大的本机方法堆栈,则Java虚拟机将抛出
StackOverflowError
。
- 如果可以动态扩展本机方法堆栈并尝试进行本机方法堆栈扩展,但可以提供足够的内存,或者可以提供足够的内存来为新线程创建初始本机方法堆栈,则Java虚拟机将抛出
OutOfMemoryError
。
The pc
Register:程序计数器
The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own
pc
(program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is notnative
, thepc
register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread isnative
, the value of the Java Virtual Machine’spc
register is undefined. The Java Virtual Machine’spc
register is wide enough to hold areturnAddress
or a native pointer on the specific platform.
Java虚拟机可以一次支持多个执行线程(JLS§17)。每个Java虚拟机线程都有其自己的
pc
(程序计数器)寄存器。在任何时候,每个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法(第2.6节)。如果不是native
,则该pc
寄存器包含当前正在执行的Java虚拟机指令的地址。如果线程当前正在执行的方法是native
,则Java虚拟机的pc
寄存器值未定义。Java虚拟机的pc
寄存器足够宽,可以returnAddress
在特定平台上保存一个或本机指针。
Run-Time Constant Pool:运行时常量池
ranging from numeric literals known at compile-time to method and field references that must be resolved at run-time. The run-time constant pool serves a function similar to that of a symbol table for a conventional programming language, although it contains a wider range of data than a typical symbol table.
Each run-time constant pool is allocated from the Java Virtual Machine’s method area (§2.5.4). The run-time constant pool for a class or interface is constructed when the class or interface is created (§5.3) by the Java Virtual Machine.
The following exceptional condition is associated with the construction of the run-time constant pool for a class or interface:
See §5 (Loading, Linking, and Initializing) for information about the construction of the run-time constant pool.
_运行时常量池_是的每个类或每个接口的运行时表示
constant_pool
在表class
文件(§4.4)。它包含多种常量,范围从编译时已知的数字文字到必须在运行时解析的方法和字段引用。运行时常量池的功能类似于常规编程语言的符号表,尽管它包含的数据范围比典型的符号表还大。
每个运行时常量池都是从Java虚拟机的方法区(Method Area 第2.5.4节)分配的。由Java虚拟机创建类或接口(第5.3节)时,将为类或接口构造运行时常量池。
以下异常条件与类或接口的运行时常量池的构造相关联:
- 创建类或接口时,如果运行时常量池的构造所需的内存超过Java虚拟机的方法区域中可用的内存,则Java虚拟机将抛出
OutOfMemoryError
。
有关 运行时常量池的构造信息,请参见§5(加载,链接和初始化)。
之所以没有运行时常量池,是因为运行时常量池是由方法区分配的,可以理解为运行时常量池包含在方法区中。
方法区,包含了运行时常量池
Method Area
JDK1.7 之前 —> Perm Space 永久代
JDK1.8 之后 —> Meta Space 元空间
2.3 Java虚拟机栈,压栈帧 执行方法的操作过程
可以对class文件进行反编译,就能够看到字节码指令,就能够看到方法执行的过程
命令:javap -c Person.class
class com.ph.jvm.Person {
com.ph.jvm.Person();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.“”😦)V
4: aload_0
5: ldc #2 // String Jack
7: putfield #3 // Field name:Ljava/lang/String;
10: aload_0
11: ldc2_w #4 // double 100.0d
14: putfield #6 // Field salary:D
17: return
public void say();
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #8 // String Person say…
5: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
public static int calc(int, int);
Code:
0: iconst_3
1: istore_0
2: iload_0
3: iload_1
4: iadd
5: istore_2
6: iload_2
7: ireturn
public static void main(java.lang.String[]);
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1
4: iconst_2
5: invokestatic #10 // Method calc:(II)I
8: invokevirtual #11 // Method java/io/PrintStream.println:(I)V
11: return
}
下面对calc()方法进行分析:
public static int calc(int op1, int op2) {
op1 = 3;
int result = op1 + op2;
// Object o = obj;
return result;
}
public static int calc(int, int);
Code:
0: iconst_3 —> 3(int)值入栈。
1: istore_0 —> 将栈顶int类型值保存到局部变量0中。 # 3这个数值从操作数栈中弹出来,赋值给局部变量中的op1
2: iload_0 —> 从局部变量0中装载int类型值入栈。
3: iload_1 —> 从局部变量1中装载int类型值入栈。
4: iadd —> 将栈顶两long类型数相加,结果入栈。
5: istore_2 —> 将栈顶int类型值保存到局部变量2中。
6: iload_2 —> 从局部变量2中装载int类型值入栈。
7: ireturn —> void函数返回。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
—> void函数返回。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-sqSn29u6-1715763235686)]
[外链图片转存中…(img-CFwbtAba-1715763235687)]
[外链图片转存中…(img-wuKbHDvX-1715763235687)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!