zl程序教程

您现在的位置是:首页 >  Java

当前栏目

JVM 一张图带你了解内存分配过程 搞懂逃逸分析|标量替换|指针碰撞|空闲列表|TLAB

2023-02-18 16:38:04 时间

B站搜索“乐哥聊编程“有本篇文章配套视频‍ https://www.bilibili.com/video/BV1pG4y147xW

面试题

在栈上分配对象,使用标量替换的目的是什么?

内存分配过程

逃逸分析

如何确定对象是否在栈上进行分配,当然得通过逃逸分析了。逃逸分析是什么意思呢?我们直接看两段代码 代码1:

public Student get(){
    Student student = new Student();
    student.setName("乐哥聊编程");
    student.setStuNo("乐哥聊编程");
    student.setAge(23);
    return student;
}

代码2:

public void save(){
    Student student = new Student();
    student.setName("乐哥聊编程");
    student.setStuNo("乐哥聊编程");
    student.setAge(23);
    // 保存到数据
}

比对两段代码,如果jvm开启逃逸分析:那么代码1在经过逃逸分析之后:student不允许对象在栈上分配 那么代码2在经过逃逸分析之后:student允许对象在栈上分配

为什么会这样呢?因为虚拟机在分析代码1后,发现student对象生成之后,被返回了,使用范围不止在当前方法,所以如果在栈上分配的话,那么当前方法结束后,对象就会被移除,但是此时对象是返回给当前方法的调用者的,导致拿到的是空的,最终导致程序出现问题。

同样道理,在分析代码2之后,student只在当前方法使用,所以允许在栈上分配.

标量替换

当通过逃逸分析之后,如果对象在栈上分配,jvm将会通过标量替换拆解对象。标量替换 = 将对象拆解成不能再分为止 聚合量 =对象中可以再次被分解的属性

public class Student {
    private String name;
    private String stuNo;
    private Teacher teacher;
    private int age;
}

Student对象首先拆解成name,stuNo,age 然后继续拆解Teacher对象,同样拆解方式。

内存划分方式

指针碰撞

将内存对半拆分,中间放一个指针,指针左边是已分配内存空间,右边是空闲内存空间。申请内存地址时,指针向右移动

空闲列表

空闲列表记录了哪段内存地址是空闲的,申请内存空间时,从这个空闲列表中的区域获取内存地址。

如果解决内存分配并发问题?

  • CAS

compareAndSwap(a,oldValue,newValue)

  • TLAB (本地线程分配缓冲区)

每个线程预先在堆中预先分配一小块内存