Java虚拟机

Java虚拟机

java内存区域以及内存区域溢出异常

线程共享,最大,存放的是对象实例。是垃圾回收期主要工作的区域。

方法区

线程共享,主要存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。

线程私有,虚拟机栈描述的是Java执行的内存模型,每个方法在执行的时候会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。

程序计数器

线程私有,是当前线程所执行的字节码的行号指示器,每个线程独立拥有,各线程之间的程序计数器互不影响。

常量池

是方法区的一部分。用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载完成后进入方法取的运行时常量池中存放。

运行时常量池相对于class文件常量池的重要特性是具备动态性。Java语言并不要求常量只在编译期产生,运行期间也有可能产生,最常见的就是String类的intern()方法。

对象的创建
1、类加载

先去常量池定位这个类的符号引用,并检查该类是否被加载,若未加载,则执行类加载过程(双亲委派);

2、分配内存

在类加载之后即可确定内存大小,然后分配内存。内存分配的方式为空闲列表和指针碰撞(这里面应该是维护了一张表,记录哪块内存是可用的)。其中,在分配内存的时候,还会涉及到线程安全问题,第一中是使用CAS配上失败重试的方式保证更新操作的原子性,还有一种是把内存分配的动作按照线程划分到不同的空间进行。

3、将内存空间初始化为0值

内存分配完,虚拟机需要将分配到的内存空间都初始化为0值,不包含对象头。

4、虚拟机对对象进行必要的设置

例如这个对象是哪个类的实例,如何才能找到类的元数据信息,对象的hash码,对象的GC分代年龄信息等。根据虚拟机当前的运行状态不同,是否使用偏向锁等。

5、初始化(init())

赋值

对象的内存布局

对象在存储中的布局分为三块区域:对象头,实例数据,对齐补充。

对象头包含两部分信息:

第一部分用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志,持有的锁,偏向线程ID等。

第二部分是类型指针,即对象指向他的类元数据指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

实例数据:

实例数据部分指的是对象真正存储的信息,包含从父类继承的,子类定义的等。

对齐补充:

对齐补充不是必然的,他起着占位符的作用,因为系统要求对象的大小是8字节的整倍数。

对象的访问定位

Java程序通过栈上的reference数据来操作堆上的具体对象,reference类型在虚拟机规范中规定了一个指向对象的引用,目前有句柄和直接指针两种。

句柄访问的好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针。

直接引用的好处是速度更快,少了一步指针定位的时间开销。

内存溢出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shichangle01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值