JVM之对象分配:栈上分配 & TLAB分配
1. Java对象分配流程

2. 栈上分配
2.1 本质:Java虚拟机提供的一项优化技术
2.2 基本思想: 将线程私有的对象打散分配在栈上
2.3 优点:
2.3.1 可以在函数调用结束后自行销毁对象,不需要垃圾回收器的介入,有效避免垃圾回收带来的负面影响
2.3.2 栈上分配速度快,提高系统性能
2.4 局限性: 栈空间小,对于大对象无法实现栈上分配
2.4 技术基础: 逃逸分析
2.4.1 逃逸分析的目的: 判断对象的作用域是否超出函数体[即:判断是否逃逸出函数体]
//user的作用域超出了函数setUser的范围,是逃逸对象
//当函数结束调用时,不会自行销毁user
private User user;
public void setUser(){
user = new User();
user.setId(1);
user.setName("blueStarWei");
} //u只在函数内部生效,不是逃逸对象
//当函数调用结束,会自行销毁对象u
public void createUser(){
User u = new User();
u.setId(2);
u.setName("JVM");
}
2.5 栈上分配示例
package com.blueStarWei.templet;
public class AllotOnStack {
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
alloc();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static void alloc() {
User user = new User();
user.setId(1);
user.setName("blueStarWei");
}
}
2.5.1 上述代码调用了1亿次alloc(),如果是分配到堆上,大概需要1.5GB的堆空间,如果堆空间小于该值,必然会触发GC。
2.5.2 使用如下参数运行,发现不会触发GC
-server -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations
2.5.3 使用如下参数(任意一行)运行,会发现触大量GC
//不使用逃逸分析
-server -Xmx15m -Xms15m -XX:-DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations //不使用标量替换
-server -Xmx15m -Xms15m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:-EliminateAllocations
2.5.3.1 可以发现:栈上分配依赖于逃逸分析和标量替换
2.5.4 GC日志
[GC (Allocation Failure) 4095K->528K(15872K), 0.0025208 secs]
[GC (Allocation Failure) 4624K->552K(15872K), 0.0012518 secs]
[GC (Allocation Failure) 4648K->608K(15872K), 0.0009262 secs]
......(省略)
3718
2.5.4.1 GC日志解析
| 参数 |
作用 |
备注 |
| GC |
用来区分是 Minor GC 还是 Full GC 的标志(Flag). |
这里的 |
Allocation Failure |
引起垃圾回收的原因. | 本次GC是因为年轻代中没有任何合适的区域能够存放需要分配的数据结构而触发的. |
4095K->528K |
在本次GC之前和之后的年轻代内存使用情况. | 本次GC前,年轻代使用空间4095K, GC后年轻代使用空间为528K |
(15872K) |
年轻代的总的大小 | |
0.0025208 secs |
本次GC使用时间(单位:秒) |
2.5.5 JVM参数解析
| 参数 | 作用 | 备注 |
-server |
使用server模式 | 只有在server模式下,才可以弃用逃逸分析 |
-Xmx15m |
设置最大堆空间为15m | 如果在堆上分配,必然触发大量GC |
-Xms15m |
设初始对空间为15m | |
-XX:+DoEscapeAnalysis |
启用逃逸分析 | 默认启用 |
-XX:-DoEscapeAnalysis |
关闭逃逸分析 | |
-XX:+PrintGC |
打印GC日志 | |
| -XX:-UseTLAB | 关闭TLAB |
TLAB(Thread Local Allocation Buffer) 线程本地分配缓存区 |
-XX:+EliminateAllocations |
启用标量替换,允许对象打散分配到栈上 |
默认启用 |
-XX:-EliminateAllocations |
关闭标量替换 |
3. TLAB 分配
TLAB,全称Thread Local Allocation Buffer, 即:线程本地分配缓存。这是一块线程专用的内存分配区域。TLAB占用的是eden区的空间。在TLAB启用的情况下(默认开启),JVM会为每一个线程分配一块TLAB区域。
3.1 为什么需要TLAB?
这是为了加速对象的分配。由于对象一般分配在堆上,而堆是线程共用的,因此可能会有多个线程在堆上申请空间,而每一次的对象分配都必须线程同步,会使分配的效率下降。考虑到对象分配几乎是Java中最常用的操作,因此JVM使用了TLAB这样的线程专有区域来避免多线程冲突,提高对象分配的效率。
3.2 局限性: TLAB空间一般不会太大(占用eden区),所以大对象无法进行TLAB分配,只能直接分配到堆上。
3.3 分配策略:
一个100KB的TLAB区域,如果已经使用了80KB,当需要分配一个30KB的对象时,TLAB是如何分配的呢?
此时,虚拟机有两种选择:第一,废弃当前的TLAB(会浪费20KB的空3.4 间);第二,将这个30KB的对象直接分配到堆上,保留当前TLAB(当有小于20KB的对象请求TLAB分配时可以直接使用该TLAB区域)。
JVM选择的策略是:在虚拟机内部维护一个叫refill_waste的值,当请求对象大于refill_waste时,会选择在堆中分配,反之,则会废弃当前TLAB,新建TLAB来分配新对象。
【默认情况下,TLAB和refill_waste都是会在运行时不断调整的,使系统的运行状态达到最优。】
3.4 JVM参数解析
| 参数 | 作用 | 备注 |
| -XX:+UseTLAB | 启用TLAB | 默认启用 |
| -XX:TLABRefillWasteFraction | 设置允许空间浪费的比例 | 默认值:64,即:使用1/64的TLAB空间大小作为refill_waste值 |
| -XX:-ResizeTLAB | 禁止系统自动调整TLAB大小 | |
| -XX:TLABSize | 指定TLAB大小 | 单位:B |
4. 附件
4.1 User类
packagepackag com.blueStarWei.templet;
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
5. 参考文献
5.1 《实战Java虚拟机 - JVM故障诊断与性能优化》
5.2 栈上分配、TLAB : https://blog.csdn.net/yangsnow_rain_wind/article/details/80434323
5.3 快速解读GC日志 : https://blog.csdn.net/renfufei/article/details/49230943
JVM之对象分配:栈上分配 & TLAB分配的更多相关文章
- 【深入浅出-JVM】(7):栈上分配
概念 对那些作用于不会逃逸出方法的对象,在分配内存时,不在将对象分配在堆内存中,而是将对象属性打散后分配在线程私有栈内存上,这样随着方法调用结束,栈上分配打散的对象也被回收掉,不在增加 GC 额外压力 ...
- 请问什么时候对象分配会不在 TLAB 内分配
Java 对象分配流程 我们这里不考虑栈上分配,这些会在 JIT 的章节详细分析,我们这里考虑的是无法栈上分配需要共享的对象. 对于 HotSpot JVM 实现,所有的 GC 算法的实现都是一种对于 ...
- LWJGL3的内存管理,第二篇,栈上分配
LWJGL3的内存管理,第二篇,栈上分配 简介 为了讨论LWJGL在内存分配方面的设计,本文将作为该系列随笔中的第二篇,用来讨论在栈上进行内存分配的策略,该策略在 LWJGL3 中体现为以 Memor ...
- Java中的栈上分配
博客搬家自https://my.oschina.net/itsyizu/blog/ 什么是栈上分配 栈上分配是java虚拟机提供的一种优化技术,基本思想是对于那些线程私有的对象(指的是不可能被其他线程 ...
- 【LWJGL3】LWJGL3的内存分配设计,第一篇,栈上分配
简介 LWJGL (Lightweight Java Game Library 3),是一个支持OpenGL,OpenAl,Opengl ES,Vulkan等的Java绑定库.<我的世界> ...
- Qt浅谈之一:内存泄露(总结),对于QWidget可以setAttribute(Qt::WA_DeleteOnClose),而且绝对不能手动删除栈上的对象
一.简介 Qt内存管理机制:Qt 在内部能够维护对象的层次结构.对于可视元素,这种层次结构就是子组件与父组件的关系:对于非可视元素,则是一个对象与另一个对象的从属关系.在 Qt 中,在 Qt 中,删除 ...
- new 的对象如何不分配在堆而分配在栈上(方法逃逸等)
当能够明确对象不会发生逃逸时,就可以对这个对象做一个优化,不将其分配到堆上,而是直接分配到栈上,这样在方法结束时,这个对象就会随着方法的出栈而销毁,这样就可以减少垃圾回收的压力. 如方法逃逸. 逃逸分 ...
- Java对象栈上分配
转自 https://blog.csdn.net/o9109003234/article/details/101365108 在学习Java的过程中,很多喜欢说new出来的对象分配一定在对上: 其实不 ...
- 深入探究JVM之对象创建及分配策略
@ 目录 前言 正文 一.对象的创建方式 二.对象的创建过程 对象在哪里创建 分配内存 对象的内存布局 三.对象的访问定位 四.判断对象的存活 对象生死 回收方法区 引用 对象的自我拯救 五.对象的分 ...
随机推荐
- nginx官方模块之http_sub_status_module
作用 显示nginx的连接状态,nginx客户端状态 配置语法 配置
- Git- 命令及使用
关于Git相关介绍这里就不介绍了,可转<Git- 简介>或者查看官网信息.这篇整理一下git相关的命令. 1) 远程仓库相关命令 克隆下载仓库:$ git clone git://gi ...
- python并发编程之多线程2------------死锁与递归锁,信号量等
一.死锁现象与递归锁 进程也是有死锁的 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去.此时称系统处于死锁状态或系统 ...
- WireShark Wifi认证数据包分析(论文idea)
1.使用 wireShark捕获802.11数据帧结构分成三种,管理帧.控制帧.数据帧. 使用的过滤语法: 过滤MAC 地址: Waln.bssid eq=8c:23:0c:44:21:0f 过滤特定 ...
- Kali linux Nessus &Cracking Password
1 .Nessus漏洞网站测试(真正体会到什么是专业版和社区版的区别,要技术就不光要勤恳的态度,严谨的思维.还有矢志不渝的志气,还必须要求砸钱,所以狠狠的赚钱才是硬道理),我的半个社区版的很多扫描模块 ...
- Allegro PCB Design GXL (legacy) 使用slide无法将走线推挤到焊盘的原因
Allegro PCB Design GXL (legacy) version 16.6-2015 启用slide命令之后,单击鼠标右键,取消“Enhanced Pad Entry”即可.
- Jmeter中使用外部的java文件
感觉在Jmeter中使用外部的Java文件比较方便,语法一样,而且可以直接引用,所以个人觉得这个功能还是蛮重要的,特别是在使用Jmeter的过程中,可能需要结合一定的业务场景进行判断等,那使用Jmet ...
- Tomcat使用
打开Tomcat官网 在浏览器地址栏输入: tomcat.apache.org,按回车 下载Tomcat 把目光移动至网页左边红匡处,点击Tomcat8 网页下移 点击箭头所指的链接 运行Tomcat ...
- javac选项以递归方式编译给定目录下的所有Java文件 - IT屋-程序员软件开发技术分享社区
http://www.it1352.com/539276.html #Linux $ find -name“* .java”> sources.txt $ javac @ sources.txt ...
- 一脸懵逼学习KafKa集群的安装搭建--(一种高吞吐量的分布式发布订阅消息系统)
kafka的前言知识: :Kafka是什么? 在流式计算中,Kafka一般用来缓存数据,Storm通过消费Kafka的数据进行计算.kafka是一个生产-消费模型. Producer:生产者,只负责数 ...