JVM--运行时数据区--java堆(Java Heap)


java堆

基本概述

  • java堆是虚拟机所管理的内存中最大的一块,在jvm启动时创建堆空间
  • java堆被所有线程共享(可以划分出多个线程私有的分配缓存区TLAB),一个JVM实例只存在一个java堆
  • java堆在物理上可以处以不连续的内存空间,但在逻辑上必须是连续的

核心概述

  • 《Java虚拟机规范》中对Java堆的描述是:“所有的对象实例以及数组都应当在堆上分配”,但是由于即时编译技术的进步、逃逸分析技术的日渐强大,栈上分配、标量替换优化手段使得java对象实例都在堆上分配也变得不绝对了
  • 数组和对象可能永远不会存储在栈上,因为栈针局部变量表中保存的是引用类型对象的引用指针,这个指针指向对象或数组在堆中的位置
  • 方法运行结束后,不会回收堆中的对象,只有等GC执行后,才会根据条件进行回收
  • 堆是GC的重点区域

内存结构

在这里插入图片描述

堆空间大小

  • 堆的初始空间大小在JVM启动时就已经设定好了

“-Xms”用来表示堆区的起始内存,等价于-XX:InitialHeapSize
“-Xmx”用来表示堆区的最大内存,等价于-XX:MaxHeapSize

  • 一旦堆区内对象的存储空间所需要的大小超过了-Xmx指定的大小,就会报OOM异常
  • 一般情况下,将-Xms和-Xmx配成一样的大小,也就是说堆区大小是固定的;这样可以在GC清理完堆区后不需要重新分配计算堆的大小,从而提高性能
  • 默认情况下,初始堆内存大小 = 电脑初始内存 / 64;堆内存最大 = 电脑初始内存 / 4

TLAB(Thread Local Allocation Buffer)

为什么要有TLAB?

        堆区是共享区域,任何线程都可以访问堆的共享区域,而由于对象创建十分频繁,所以并发环境下创建对象是线程不安全的,可能存在多个线程共同操作同一地址,为了解决这个问题,需要使用加锁等机制,而加锁是比较耗时的操作
        经过上述问题,jvm在堆区的新生代的Eden空间中提供了线程私有缓冲区域TLAB,它不仅可以避免一系列的线程安全问题,还能够提升内存分配的吞吐量,因此我们将这种策略称之为快速分配策略

基本概述

  • 尽管不是所有对象实例都能在TLAB中成功分配内存,但JVM仍然将其作为内存分配的首选
  • 可以通过“-XX:UseTLAB”设置是否开启TLAB,可以通过“-XX:TLABWasteTargetPercent”设置TLAB空间所占Eden空间的百分比
  • 默认情况下,TLAB空间的内存非常小,仅占有整个Eden空间的1%,
  • 一旦对象在TLAB空间分配内存失败,JVM就会尝试通过使用加锁机制确保数据操作的原子性,从而直接在Eden空间中分配内存

TLAB内存分配过程

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值