讲完如何从Java字节码层面去理解New一个对象,面试官都懵了!

在Java的世界中,可以有多种方式生成一个对象。new是其中一种,也是使用最频繁的一种。今天咱们就来八一八new的实现细节以及与new相关的一些高端面试题。

如果你想对JVM了解更深,可以看我讲解的公开视频:JVM底层原理教程

new的实现细节我会从两个角度分析:Java字节码层面、openjdk源码层面。

与new相关的面试题有哪些呢?一、如何理解new是非原子操作?二、在高并发环境下,DCL需要加volatile,为什么?

对象大小是何时知晓的

new是用来生成对象的,对象是有大小的,那对象的大小是何时确定的呢?如果你没有看过openjdk源码,你肯定以为是在生成对象的时候动态计算的。但事实上呢,是在类加载阶段就已经计算出来了。上证据:


InstanceKlass::InstanceKlass(int vtable_len,
                             int itable_len,
                             int static_field_size,
                             int nonstatic_oop_map_size,
                             ReferenceType rt,
                             AccessFlags access_flags,
                             bool is_anonymous) {
   
……
   // Set temporary value until parseClassFile updates it with 
  //the real instance size.
  set_layout_helper(Klass::instance_layout_helper(0, true));
……

这段代码上面的注释的意思是:暂时设置一个临时值,直到parseClassFile 函数执行时用真实的实例的大小来update

还有没有证据呢?还有很多,再上一个


CASE(_new): {
   
……
    InstanceKlass* ik = (InstanceKlass*) k_entry;
    ……
    // 获取基于目标类生成的对象的大小  
    size_t obj_size = ik->size_helper();
……

这是JVM处理new指令的逻辑,可以看到这时候不是在计算对象大小,而是从InstanceKlass类型的ik中去取。

内存的分配方式

上面说到一个对象的大小是对象所属类的class文件在加载时就已经计算出来了,那现在我们知道要分配多大内存,那要如何分配呢?

这里讲到两个分配策略:指针碰撞、空闲列表。那如何理解这两个分配策略呢?JVM又是采用哪种分配策略的呢?

JVM采用何种分配策略是由当前使用的垃圾回收器决定的。为什么这么说呢?因为指针碰撞只能用于内存规整的环境中,而空闲列表就没有这样的前提条件。那全部用空闲列表不就好了,为什么还要设计指针碰撞呢?是时候对这两种策略深入讲解一下了。

指针压缩只能用于内存规整的环境中,即一边是已使用的内存,一边是未使用的内存,交界处即为碰撞处,名曰分界点的指示器。分配内存的时候是怎么做的呢?将指示器向未使用内存这边移动一段对象大小的距离,底层是通过CAS循环碰撞,CAS执行成功即碰撞成功,成功分配到内存。可以发现这种方式的核心是前期使用内存的约束要做好,因为不需要借助其他数据结构辅助实现,所以保证了分配内存的高效性。

在这里插入图片描述
JVM处理new的逻辑中就是采用的指针碰撞,因为新生代采用的是分代-复制算法,所以堆内存是规整的。看代码:


……    
    // 指针碰撞在堆区分配内存(其实就是循环执行CAS)
    retry:
          HeapWord* compare_to = *Universe::heap()->top_addr();
          HeapWord* new_top = compare_to + obj_size;
          if (new_top <= *Universe::heap()->end_addr()
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值