Java虚拟机内存分配

在java中,创建一个新的对象,在语言层面上,是一个关键字new,而在虚拟机层面上,过程却较为复杂。

Java虚拟机分配内存前

当Java虚拟机执行一个new关键字的指令时,会首先在方法区的运行时常量池中查找一个对该类的符号引用,并检查这个符号引用指向的类是否已经被加载、解析以及初始化过。如果没有上述加载、解析、初始化的过程,那必须先执行上述过程(执行过程以后再讲);如果上述过程已经执行完毕,则对新对象执行内存分配操作。

Java虚拟机分配内存原则

新的对象需要的内存大小在类加载完后就已经确定,为对象分配内存的过程其实就是在Java堆中划出一块内存确定大小的内存。
如果java堆中的内存是绝对规整的,所有已经被占用的内存放到一边,没有使用的内存放在另一边,中间是一个作为分界点的指示器,这种情况下只需要将作为分界点的指示器向未使用的内存区移动一段与新对象所需内存大小相等的距离即可,这种分配方式就是所谓的指针碰撞
如果很不幸,Java堆中的内存并不是连续一块的,已经占用的内存和闲置的内存是交错分布的,这个时候虚拟机就必须维护一个列表来记录哪些内存块是空闲可以用于分配的,在为新对象分配一个内存区域时,需要在这个表中查找到一块足够大的内存区域划分给新对象,并更新该表,这种方式就是空闲列表
Java虚拟机采用哪种分配方式由虚拟机中的内存是否规整决定,而内存的规整与否取决于虚拟机的垃圾收集器是否含有对内存的压缩整理功能。

Java虚拟机内存分配保护

Java虚拟机中内存的分配是非常频繁的,就算是分配比较快速的指针碰撞方式,也有可能会出现在为A对象分配内存移动指针的同时对象B同样适用原来位置的指针分配内存。
为解决这种问题,存在两种方案:
1. 对分配内存空间的动作进行同步处理(锁机制)
2. 把分配内存的动作按照线程划分到不同的空间中进行。也就是说,每个线程预先在Java堆中预先分配一小块内存(即本地线程分配缓冲Thread Local Allocation Buffer-TLAB),哪个线程需要分配内存的时候,就在该线程的TLAB中分配。当该线程的TLAB用完时进行重新分配,重新分配的这个过程中进行线程锁定。

Java虚拟机内存分配初始化

在给新对象分配完内存之后,需要对内存进行初始化处理,这也是新对象的实例字段可以不被赋值直接使用的原因所在,只不过不进行其他操作的情况下,此时程序访问到的是这些实例字段的默认零值而已。
这时候虚拟机要对对象进行必要的设置,例如:这个对象是哪个类的实例、如何找到类的元数据信息、对象的哈希码、GC的分代年龄等信息。
以上过程完成之后,在虚拟机角度上看,对象已经创建了,但是从java程序角度来看,对象创建才刚刚开始,因为<init>方法还没有执行,这时候所有的字段都还是零。在程序执行new指令之后会接着执行<init>方法,将对象初始化,这样,真正可用的对象才会被创建完。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值