JVM——深入理解Java内存区域

运行时数据区域

 Jvm管理的内存会被分为多个不同的数据区域

程序计数器

程序计数器是线程私有的一块内存区域,由于java的多线程的实现方式是不同线程交替执行,使得同一时刻只能有一个线程使用处理器,这就会出现一个问题,不同线程执行的的class字节码文件中的不同指令,可能会出现线程在失去处理器的使用权后,再次使用并不知道上次的执行位置,程序计数器就是独立给每个线程记录虚拟机字节码的地址的

Java虚拟机栈

java虚拟机栈也是线程私有的数据区域,虚拟机每执行一个方法,同时就会在java虚拟机栈中同步创建一个栈帧,里面存储了局部变量表,操作数栈,动态链接,方法出口等信息,方法执行的过程也代表了各种参数入栈、出栈的过程。

其中局部变量表储存的是基本数据类型,包含了int,float,char,double,boolean,byte,short,long以及renference(对象的引用)和返回值类型,这些数据类型在局部变量表中以局部变量槽的方式存储,变量槽的默认大小是32位,但如果是double和long类型的会分给两个变量槽。局部变量表的内存空间在编译的时候完成分配,当进入一个方法时局部变量表的大小也就是局部变量槽的数量就已经确定了,在方法的运行期间并不会改变局部变量表的大小也就是局部变量槽的数量

栈帧结构如下

本地方法栈

本地方法栈和java虚拟机栈的作用时十分类似的,区别就在于,java虚拟机栈执行的时java方法,本地方法栈执行的可能是C或C++的方法即本地方法

Java堆

Java堆是被所有线程共享的一块区域,几乎所有对象的实例被分配到这里。

从垃圾回收的角度来看,该区域被分为新生代和老年代两个部分,其中新生代主要负责存放占用内存比较小的对象,区域也被分为Eden区和Survivor区,老年代主要负责存放一些大对象和多次经过MinorGC没有回收完成的对象

如果从分配内存的角度看,虚拟机给每个线程都分配了一块线程私有的线程缓存区,提升对象分配的效率

方法区

方法区和java堆一样是线程共享的区域,主要存放虚拟器加载的类型信息,常量、静态变量等数据,例如类的版本号、字段、方法的描述信息,java8以前,对方法区的设计是与java堆类似的,并且也打算把收集器的分代设计应用在方法区,所以也一直把方法区叫做永久代,不过经过实践发现,这样的设计更容易导致java应用的内存溢出的问题,于是在java9以后选择了完全放弃永久代,转而用本机内存实现的元空间代替。

运行时常量池

运行时常量池是方法区的一部分,Class文件中存放编译器生成的各种字面量和符号引用的内容就存放在常量池表中,

而常量池表存放在运行时常量池中

直接内存

直接内存并不是虚拟机数据区的一部分,而是虚拟机从主机申请的内存区域,由于java应用可能会用到主机内的数据信息,通过虚拟机复制到java堆的开销比较大,所以通过直接内存操作复制来的主机内容信息,提高了虚拟机的效率,而且直接内存的分配不受java堆的大小限制,只受主机内存大小的限制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值