理解Java虚拟机(4)之JVM运行时内存分配管理和对象内存分布

理解Java虚拟机(4)之JVM运行时内存分配管理和对象内存分布

读《深入理解Java虚拟机》-周志明 读书笔记

classLoader将class文件加载进虚拟机后,就是要开始运行程序员写的代码了,要运行就要分配内存,所以先得了解虚拟机运行时内存分配管理。
JVM在执行的过程中会把它所管理的内存划分若干个不同的数据域,这种区域有不同的用途,数据区域主要分为方法区,虚拟机栈,本地方法栈,堆,程序计算器,讲讲各自的作用,图如下

image

程序计数器

程序计数器是线程私有的,是一个较小的内存空间,可以看成当前线程所执行字节码的行号指示器,字节码解释器就是通过改变这个技术器的值来选取下一条需要执行的命令,分支,循环,跳转,异常处理,线程恢复等,对操作系统有了解的话这个功能有些像cpu的计数器,各条线程的程序计数器互不影响,当线程在执行,计数器记录的是当前方法的虚拟机字节码指令位置。

虚拟机栈

虚拟机栈也是线程私有的,生命周期和线程相同,描述的是java方法内存模型,每个方法在执行的过程中,都会创建一个栈帧,栈帧用于存放局部变量表,操作数栈,动态链接,方法出口信息,每个方法从调用到执行完成,就对应这栈帧在虚拟机栈中出栈入栈的过程,局部变量表存放编译器可知的各种基本数据类型(boolean,byte,chart,short,float,int,double,long),对象引用(reference,例如Object a = new Object(),这个a就是reference)

本地方法栈

本地方法栈和虚拟机栈所发挥的作用是非常相似的,差别是本地方法栈是执行native方法,native方法是java的扩展方法,没有规定要java实现,接口实现可以用其他语言实现。

java堆

堆是线程共享的,是虚拟机管理的最大一块内存,堆主要存放对象实例,java堆也是GC回收管理的主要区域。

方法区

方法区是堆的一部分逻辑区域,但有个别名Non-Heap(非堆),也是线程共享的,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译后的代码。

运行时常量池

运行时常量池是方法区的一部分,class文件中关于常量池,主要存放字符引用,对class加载的四个阶段(验证,准备,解析,初始化),解析过程解析字符引用为直接引用,就是从这个常量池拿字符变量

对象的创建

java创建对象一般就是通过new关键字,虚拟机遇到new指令时,首先去检查是否能在常量池定位这个类的符号引用,并检查这个符号引用这个类是否被加载,解析过,如果没有将会执行加载过程,在类检查通过后,接下来虚拟机将为新对象分配内存,对象所需内存大小在加载完成后就可以确定了,给对象分配内存相当于确定一块内存从堆中划出来,假设堆内存是规整的,分配内存相当于将指针想空闲处移动一段距离,这种分配方式成为“指针碰撞”,如果java堆不是规整的,堆就需要一个表来记录哪些内存可用,找到一块够用的内存分派给这个对象,并更新列表记录,这种方式称为“空闲分配”,分配内存后,虚拟机会对这个对象进行必要设置,例如是哪个对象的实例,如何才能找到这个类的元信息,对象的哈希码值,对象GC年龄分布,这些信息存放在对象头中,这些执行完后会执行init方法,这个时候才会执行我们写的代码,
创建对象是为了使用对象,使用有2种常见方式,A:一种是程序是通过栈上的reference的指针指向堆中某个指向具体的对象的地址(句柄池)来操作具体对象,举个例子,有个Test的类,Test t=newTest(),t就相当这个reference,指向堆中一个地址,这个地址指向具体的Test实例对象,B:一种是这个reference直接指向这个对象;A这种方式好处是,reference中存储的是稳定的句柄池,在对象被移动时只会改变具体的实例数据,而reference本身不被修改,主要是稳定,B这种方式主要就是快。2种方式图分别如下

image

image

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值