JAVA虚拟机

自动内存管理
一 内存区域与内存溢出异常

1 运行时数据区域

程序计数器

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

java虚拟机栈

java虚拟机栈是线程私有的,生命周期与线程相同
虚拟机栈描述的是java方法执行的线程内存模型:
每一方法被执行的时候,java虚拟机都会同步创建一个线帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
栈(更多情况是指虚拟机栈中的局部变量表部分)
局部变量表存放了编译期可知的各种Java虚拟机基本数据类型、对象引用和returnAddress类型

本地方法栈
本地方法栈是虚拟机使用到本地方法服务

JAVA堆

java堆是虚拟机所管理的内存中最大的一块,java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存唯一的目的就是存放对象实例,
java堆是垃圾收集器管理的内存区域“GC”堆,

方法区

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

运行常量池

运行常量池属于方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外、还有一项信息是常量池表,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

直接内存

非运行时数字区域的一部分

2 HotSpot虚拟机对象探秘

对象的创建
当java遇到一条字节码new指令,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过,然后,,虚拟机将会为新生对象分配内存。
在并发情况下也并不是安全的,
解决这个问题有两种可选方案,
一种是对分配内存空间的动作进行同步处理-——实际上虚拟机上是采用CAS配上失败重试的方式保证更新操作的原子性
另一种是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存。
接着,虚拟机必须将分配到的内存空间都初始化为0值
接下来,设置对象头
对象的内存布局
在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header)、实例数据(Instance Data)和对齐填充
对象头包括两部分信息,第一类是用于存储对象自身的运行时数据,第二类是类型指针,即对象指向它的类型元素的指针。
对象的访问定位
主流的访问方式主要有使用句柄和直接指针两种方式

  • 如果使用句柄的话,java堆中将可能划分一块内存来作为句柄池 reference 中存储的就是对象的句柄地址
  • 如果使用直接指针访问的话,java堆中对象的布局就必须考虑如何放置访问类型数据的相关信息,refernce 中存储的直接就是对象地址
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值