每一个Java程序都运行于自己的Java虚拟机实例中
每一个java虚拟机实例都一个方法区和堆,装载class文件时,会将class文件中包含的二进制数据中解析类型信息放到方法区中,将所有程序在运行时创建的对象放到堆中
方法区
类型信息和类的静态变量都存储在方法区中。方法区中对于每个类存储了以下数据
a.类及其父类的全限定名(java.lang.Object没有父类)
b.类的类型(Class or Interface)
c.访问修饰符(public, abstract, final)
d.实现的接口的全限定名的列表
e.常量池
f.字段信息
g.方法信息
h.静态变量
i.ClassLoader引用
j.Class引用
新线程创建时,被分配PC寄存器和Java栈,PC寄存器的值总是指向下一条方法的执行指令,Java栈则存储Java方法调用的状态,包括局部变量,参数,返回值以及中间结果等
本地方法栈中存储本地方法的状态
class Lava{ private int speed = 5; void flow(){ } } class Volcano{ public static void mian(String[] args){ Lava lava = new Lava(); lava.flow(); } }
虚拟机找到并读入Volcano.class文件,导入class文件中的二进制数据流提取类型信息到方法区
执行main()
检查Lava类是否已经被装载
查找装载Lava.class
虚拟机以一个直接指向方法区Lava类数据指针来替换常量池第一项
虚拟机分配足够内存,初始化为0
堆
和方法区一样,可以是不连续的内存
两种实现方式
Java栈
Java栈的两种操作:以帧为单位的压栈和入栈
某线程正在执行的方法称为当前方法,当前方法使用的栈帧为当前帧,当前方法所属类为当前类,当前类的常量池为当前常量池
当线程执行一个方法时,虚拟机会在该线程的Java栈中压入一个新帧,在执行这个方法时,它使用这个帧来存储参数,局部变量,中间运算结果等
栈帧由局部变量去,操作数栈和帧数据区
addAndPrint将int 1和double 88.88压入到它的操作数栈中,调用addTwoType,解析此方法,分配内存压入栈帧,从addAndPrint操作数栈弹出int和double放在addTwoType的局部变量区,
addTwoType返回时,将返回值double 89.88压入操作数栈,虚拟机使用帧数据区的信息找到调用者addAndPrint,将返回值压入addAndPrint的操作数栈并释放addTwoType的栈帧内存,执行下一条指令
帧数据区的任务主要有:
a.记录指向类的常量池的指针,以便于解析。
b.帮助方法的正常返回,包括恢复调用该方法的栈帧,设置PC寄存器指向调用方法对应的下一条指令,把返回值压入调用栈帧的操作数栈中。
c.记录异常表,发生异常时将控制权交由对应异常的catch子句,如果没有找到对应的catch子句,会恢复调用方法的栈帧并重新抛出异常。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?