《深入理解Java虚拟机》学习总结-运行时数据区域

Java虚拟机运行时数据区域可划分为以下5个部分:虚拟机栈,本地方法栈,程序计数器,堆,方法区


虚拟机栈

虚拟机栈是线程私有的数据区,他的生命周期与线程相同。虚拟机栈中划分了若干个栈帧,每个栈帧对应了一个方法,用于存储局部变量表、操作数栈,动态链接、方法出口等信息。

1)局部变量表:局部变量表是一组变量值的存储空间,用于存储线程中方法内部定义的局部变量及方法参数,局部变量表以变量槽为最小单位,对于每一个变量槽,应该都能存放一个boolean,byte,char,short,int,float,reference或returnAddress类型的数据,对于64位的数据类型,Java虚拟机会以高位对其的方式为其分配两个连续的变量槽。Java虚拟机通过索引定位的方式使用局部变量表,索引值的范围是从0开始至局部变量表最大的变量槽数量。当一个方法被调用时,Java虚拟机会使用局部变量表来完成参数值到参数列表的传递过程,如果该方法为实例方法的话(即无static修饰符修饰的方法),则局部变量表的0号索引位置会存储this引用,需要注意的是,局部变量表的变量槽是可重用的,因为方法中局部变量的作用域不一定包括整个方法体,所以对于那些不在其作用域的变量,可以复用其变量槽,例如:

public static void main(String[] args)() {
{
byte[] placeholder = new byte[64 * 1024 * 1024];
}
int a = 0;
System.gc();
}

2)操作数栈:操作数栈是一个栈数据结构,满足先进后出原则,其中的每一个元素可以是包括long和double在内的任意Java类型,32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2.Javac编译器的数据流分析工作保证了在方法执行的任何时候,操作数栈的深度都不会超过Code属性中max_stacks数据项设定的最大值。当一个方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种 字节码指令往操作数栈中写入和提取内容,也就是出栈和入栈操作。举个例子,例如整数加法的字节码指令iadd,这条指令在运行的时候要 求操作数栈中最接近栈顶的两个元素已经存入了两个int型的数值,当执行这个指令时,会把这两个int 值出栈并相加,然后将相加的结果重新入栈。需要注意的是,虽然在概念模型中,两个不同的栈帧是作为不同方法的虚拟机栈元素,应该是完全独立的,但是在大多数虚拟机的实现中,都会对其进行一些优化,允许两个栈帧出现一部分重叠,使其节约一些空间,如下图所示:

3)动态连接:每个栈帧都包含了一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。首先,我们的Class文件的常量池中存在着大量的符号引用(符号引用存在原因我理解是在Java编译器将*.java编译成.class文件时,由于我们此时不知道被引用的类,字段,方法的内存地址,所以我们只能暂时生成符号引用,待到运行时再通过符号引用索引其内存地址),这些符号引用一部分会在类加载阶段或者第一次使用的时候就被转化为直接引用,这种转化称之为静态解析。另外一部分会在每一次运行期间都转化为直接引用,这部分称之为动态连接。这两个转化的具体过程可见方法调用部分。

4)方法返回地址:当一个方法执行时,只有两种方法可以退出,一种是正常退出(即正常调用完成),另一种是方法执行过程中遇到了异常退出(即异常调用完成)。一个方法使用异常完成出口的方式退出,是不会给它的上层调用者提供任何返回值的。无论采用何种退出方式,在方法退出之后,都必须返回最初方法被调用的位置,方法正常退出时,主调方法的PC计数器的值就可以作为返回地址,方法异常退出时,返回地址是通过异常处理器表确定的


本地方法栈

本地方法栈与虚拟机栈十分相似,其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务


Java堆

Java堆是虚拟机所管理的内存中最大的一块。Java堆是被所有线程所共享的一块内存区域,在虚拟机启动时创建。此内存的唯一目的就是存放对象实例,Java世界‘几乎’所有对象实例都会在这里分配内存(判定为不会线程逃逸的对象实例也可在栈上分配)

Java堆是垃圾收集器管理的内存区域,因此一些资料中他也被称为‘GC堆’。

所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区,以提升对象分配时的效率,需要注意的是,无论是哪个区域,Java堆中存储的都只能是对象的实例,将Java堆细分的目的只是为了更好的回收内存,更快的分配内存

《Java虚拟机规范》规定,Java堆可以处于物理上的不连续内存空间中,但在逻辑上它应该被视为连续的

Java堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩展来实现的


方法区

方法区和Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。

方法区在JDK8以前,习惯被称之为永久代,但实际上方法区不能等同于永久代,永久代只能说是方法区的一种实现方法。

《Java虚拟机规范》对方法区的约束非常宽松,它内存也和Java堆一样可以物理上不连续,可选择固定大小或可扩展方式,甚至还可以选择不实现垃圾收集,不过实际情况中,对于这一部分的垃圾收集还是相当有必要的。这区域的内存回收主要是针对常量池的回收和对类型的写在。


程序计数器

程序计数器是一块比较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器,为了线程切换后能回复到正确的执行位置,每个线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响


附网上找的两张图

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值