JVM中堆、栈、方法区之间怎么交互
程序员文章站
2022-05-04 08:50:22
作者之前都只是了解堆、栈、方法区中存储什么数据,但是对彼此之间的数据交互一直不太清楚(奈何技术太菜)。在查阅了资料之后对这方面有了了解,记录一下该知识点。作者技术有限,如有错误请指出。如下图所示来讲解堆,栈,方法区交互,此文默认您已经了解了jvm的运行时数据区域,在此基础上进行讲解。如图所示:首先创建两个类,用于讲解。public class Yi_ding{ //运行时把加载之后的Yi_ding的信息存入方法区(类型信息、常量、静态变量、方法信息等) public static voi...
作者之前都只是了解堆、栈、方法区中存储什么数据,但是对彼此之间的数据交互一直不太清楚(奈何技术太菜)。在查阅了资料之后对这方面有了了解,记录一下该知识点。作者技术有限,如有错误请指出。
如下图所示来讲解堆,栈,方法区交互,此文默认您已经了解了jvm的运行时数据区域,在此基础上进行讲解。如图所示:
首先创建两个类,用于讲解。
public class Yi_ding{ //运行时把加载之后的Yi_ding的信息存入方法区(类型信息、常量、静态变量、方法信息等)
public static void main(String[] args) {
Function function = new Function(); //function是对象引用存在栈中,new Funciotn()的实例放在堆中(包含方法区中的类型信息(方法信息等)引用等)。
function.out2(); //调用out2方法
}
}
public class Function{ //运行时把加载之后的Function的信息存入方法区(类型信息、常量、静态变量、方法信息等)
public void out1(){
System.out.println("我是Function的方法");
}
public void out2(){
out1(); //这块调用out1主要是为了展示栈帧和栈帧中的动态链接
System.out.println("我是Yi_ding的方法");
}
}
执行过程如下:
- 首先启动Java虚拟机进程,通过类加载机制加载编译之后的Yi_ding.class文件。
- 接着,JVM定位到方法区中Yi_ding类的Main()方法的字节码,开始执行它的指令。接着执行第一条语句:Function function = new Function();
让JVM创建一个Function 实例,并且,使引用变量function 引用这个实例。过程如下
1)、加载Function类, 把Function类的相关信息存放在了方法区中。
2)、Function类的相关信息加载完成后。Java虚拟机做的第一件事情就是在堆中为一个新的Function类的实例分配内存,这个Function类的实例持有着指向方法区的Function类的类型信息的引用(Java中引用就是内存地址)。这里所说的引用,实际上指的是Function类的类型信息在方法区中的内存地址。
3)、在JVM中的一个进程中,每个线程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素被称为栈帧,每当线程调用一个方法的时候就会向方法栈中压入一个新栈帧。这里的帧用来存储方法的参数、局部变量和运算过程中的临时数据。位于“=”前的function 是一个在main()方法中定义的变量,可见,它是一个局部变量,因此,function 这个局部变量会被JVM添加到执行main()方法的主线程的Java方法调用栈中。而“=”将把这个function 变量指向堆区中的Function实例,也就是说,function 这个局部变量持有指向Function类的实例的引用(即内存地址)。
4)、JVM将继续执行后续指令,在堆区里继续创建另一个Function类的实例,然后执行out方法。当JVM执行function.out2()方法时,JVM根据局部变量function持有的引用,定位到堆中的Function类的实例,再根据Function类的实例持有的引用,定位到方法区中Function类的类型信息(包括①类,②静态变量,③静态方法,④常量和⑤成员方法),从而获取out2()成员方法的字节码,将out2()方法进行压栈操作,当执行out2()方法中的out1()方法时就涉及到动态链接。
在 Java 源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在 Class 文件的常量池中。比如:描述一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用。此时根据动态链接将out1()方法压栈。然后执行out1()方法中的指令出栈,执行out2()方法中的指令出栈。
该图片来自网络
参考文章
https://blog.csdn.net/zhmi_1015/article/details/92796016
本文地址:https://blog.csdn.net/qq_37909141/article/details/107341443
上一篇: Java多线程学习笔记一
下一篇: 多线程下List 如何解决不安全问题
推荐阅读
-
JVM中堆、栈、方法区之间怎么交互
-
JVM 内存初学 (堆(heap)、栈(stack)和方法区(method) )(转载)
-
java虚拟机栈中,一个对象变量、方法等对应在jvm运行时数据区中的位置
-
OOM实战:堆内存溢出 虚拟机栈和本地方法栈溢出 jvm栈容量太小 栈帧太大 栈太小,导致线程分配少,创建更多的线程将导致oom 方法区和运行时常量池溢出
-
【Mark学Java】Java中的堆 栈 方法区
-
JVM---栈、堆、方法区的交互关系
-
JVM中堆、栈、方法区之间怎么交互
-
简单介绍java中堆区、方法区和栈区的代码实例
-
[二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
-
简单介绍java中堆区、方法区和栈区的代码实例