java对象的创建与内存分配机制
文章目录
- 对象的创建与内存分配机制
- 对象的创建
- 类加载检查
- 分配内存
- 初始化零值
- 设置对象头
- 指向init方法
- 其他:指针压缩
- 对象内存分配
- 对象在栈上分配
- 对象在Eden区中分配
- 大对象直接分配到老年代
- 长期存活的对象进入老年代
- 对象动态年龄判断
- 老年代空间分配担保机制
- 对象的内存回收
- 垃圾标记算法
- 常见的引用类型
- finalize()方法
- 如何判断一个类是无用的类
对象的创建与内存分配机制
对象的创建
java中对象的创建过程如下图所示分为这几步:类加载检查、分配内存、初始化、设置对象头、执行init方法
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bL9W0Ebb-1678459769746)(picture/性能调优/123315)]](https://img-blog.csdnimg.cn/26e9af4d4d7a48149f08588e2542bef5.png)
类加载检查
检查当前要创建对象所对应的类是否被加载过,类元数据信息是否已经在方法区中保存过,如果没有则会去进行类加载的过程,如果加载了则进行下一步
分配内存
这一部分需要考虑两点:
- 应该将哪一块内存区域分配给对象
- 如何解决多个线程并发分配同一块内存问题
如何分配内存
java中有两种为对象分配内存的方式:
-
指针碰撞(Bump the Pointer) 默认使用
对于绝对工整的内存区域,一边是已经分配的内存,一边是未分配的内存,中间有一个指针分割。
经过内加载后就已经知道了此对象会占用多大的内存,从指针位置开始往后分配一块内存给该对象
-
空闲列表(Free List)
对于内存比较碎片化,部署绝对工整的情况,就需要使用空闲列表机制来分配内存了,JVM底层会维护一个空闲列表,然后选出一块合适该对象的内存区域进行分配
解决并发分配问题
在多线程的情况下,就可以会出现多个线程都再指针移动前读取到了当前指针的位置,然后把后面的一块内存区域进行了重复分配。解决这个问题有两种方法:
-
CAS算法
再使用内存前先进行一次验证,比如判断指针是否移动了,如果验证不通过则进行重试
-
TLAB,JDK8默认使用
本地线程分配缓冲(Thread Local Allocation Buffer,TLAB)
为每个线程在Eden区中事先分配一块内存区域,各个线程就在自己的这块区域中进行分配,这样就不会有并发问题,当这块内存区域不够使用时在使用CAS算法在Eden去中分配
通过
-XX:+/-UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开启-XX:+UseTLAB),-XX:TLABSize指定TLAB大小。
初始化零值
为对象的属性赋零值,这里需要注意,在类加载的时候是操作的静态变量,而这里才是操作的普通成员变量
初始化零值的作用是:避免了对象属性没有初始化就被使用
设置对象头
对象头的作用是:保存Hash值、分代年龄、锁信息、指向方法区中的类元信息等等
java的对象一般分为三部分:对象头、实例属性、对其填充
- 对象头接下来详细讲
- 实例属性:保存此对象各个属性的值
- 对其填充:保证整个对象占用内存是8字节的整数倍
对象头如下图所示又分为三个部分
-
mark word标记阶段
记录对象hash值、分代年龄、锁信息。32位机器占4字节,64为机器占8字节
-
Klass point 类型指针
指向方法区中类元数据。64位机器开启指针压缩后占4字节,否则占8字节
虚拟机通过这个指针来确定这个对象是哪个类的实例。
-
数组长度:只有数组对象才有,占4字节
32位机器中的对象头信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QqDuJNwb-1678459769747)(picture/性能调优/123316)]](https://img-blog.csdnimg.cn/b3b758eab894410bba984523d49a90c1.png)
64位机器中的对象头信息
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i4ZEN4f0-1678459769747)(picture/性能调优/123317)]](https://img-blog.csdnimg.cn/9c1edfe987d04fe1bd177a936469e6c3.png)
指向init方法
对成员变量赋程序员自定义的值,并调用对象的构造方法
其他:指针压缩
JDK1.6开始,对于64为的机器默认是开启指针压缩的
启用指针压缩:-XX:+UseCompressedOops(默认开启),禁止指针压缩:-XX:-UseCompressedOops
之所以要使用指针压缩最主要的原因就是节约堆的内存使用
对象内存分配
一个对象的内存分配过程大致如下图所示
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-99q9JK41-1678459769747)(picture/性能调优/123318)]](https://img-blog.csdnimg.cn/0ea5e8129b2d4511bcf495d2409ae5c9.png)
对象在栈上分配
我们创建一个对象其实最开始的时候会判断该对象是否能够在栈上分配,目的是减轻GC的压力,当方法执行完 出栈后,这一块栈帧内存区域也就被回收了
经过逃逸分析,我们就能判断此对象是否能在栈上分配,其实就是看此对象有没有在该方法之外的地方被引用,是否有作为方法的返回值给其他地方引用。
同时还有标量替换机制,对象是需要一块连续的内存空间,而栈帧的内存可能没有这么大的一块连续的内存空间分配给对象,而标量替换就是将对象拆开,分散存储对象的成员属性。
标量与聚合量,java的基本类型就是标量,java的对象就是聚合量
逃逸分析和标量替换JDK1.7之后都是默认开启的,逃逸分析开关-XX:+DoEscapeAnalysis 标量替换开关-XX:+EliminateAllocations
对象在Eden区中分配
年轻代默认占用堆的1/3内存,其中Eden区大致占用8/10,S0占用1/10, S1占用1/10
JVM参数-XX:+UseAdaptiveSizePolicy(默认开启),会导致这个8:1:1比例自动变化,如果不想这个比例有变化可以设置参数-XX:-UseAdaptiveSizePolicy
一般情况下对象会在Eden区中创建,当存满后进行MinorGC,将存活的对象移至S0区,下一次MinorGC就回收Eden区和S0区,将存活对象移至S1,这其中分代年龄一直递增,默认达到15后就移至老年代
如果一个对象在经过MinorGC后,Survicor的剩余空间不足已存放该对象,这个对象就会提前 直接进入到老年代中
当老年代内存使用满后触发FullGC,回收堆和方法区的内存
大对象直接分配到老年代
JVM的参数 -XX:PretenureSizeThreshold能配置超过这个存储空间的对象就是大对象,直接分配到老年代中,目的是减少大对象来回拷贝占用Survicor的空间
这个参数只在 Serial 和ParNew两个收集器下有效。
所以我们一般都是两个参数一起设置JVM参数:-XX:PretenureSizeThreshold=1000000 (单位是字节) -XX:+UseSerialGC
长期存活的对象进入老年代
对象每经过一次GC,如果还存活该对象年龄则+1,默认达到15次后就进入老年代,CMS收集器默认6岁,不同的垃圾收集器会略微有点不同
对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设
对象动态年龄判断
经过一次MinorGC后,存活的对象会存放在Survicor区,这一批对象总大小如果大于了当前Servicor区内存的一半,此时对象年龄大于等于这批对象最大年龄的对象就直接进入到老年代,比如此时Servicor区现有一些对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代
-XX:TargetSurvivorRatio 目标存活率,默认为50%
对象动态年龄判断机制一般是在minor gc之后触发的。
老年代空间分配担保机制
每经过一个MinorGC前都会计算当前老年代剩余可用空间,判断老年代剩余可用空间是否小于年轻代所有对象总大小
如果小于则检查当前是否有-XX:-HandlePromotionFailure参数,JDK8默认有
如果有这个参数则判断当前老年代剩余可用空间是否小于以往MinorGC移入老年代对象内存空间的平均值
如果小于或者上一步参数没有配置则直接进行FullGC,之后其实还是会进行一次MinorGC
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c1BrSxtg-1678459769747)(picture/性能调优/123319)]](https://img-blog.csdnimg.cn/1cba88d5a6bc4ac9a1d9cd734f6c225e.png)
对象的内存回收
垃圾标记算法
- 引用计数法,对象循环引用问题无法解决
- 可达性分析算法,一般默认使用的这种算法,从GCRoot对象开始向下寻找引用。GFRoot对象是栈帧的成员变量、静态变量
常见的引用类型
-
强引用
普通的变量引用,GC不会被清理
-
软引用
将对象用SoftReference对象包裹,正常情况下不会被回收,如果经过一次GC后还是释放不出空间存放新的对象则会将软引用的对象回收
public static SoftReference<User> user = new SoftReference<User>(new User()); -
弱引用
将对象用WeakReference软引用类型的对象包裹,弱引用跟没引用差不多,GC会直接回收掉,很少用
public static WeakReference<User> user = new WeakReference<User>(new User()); -
虚引用
虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系,几乎不用
finalize()方法
finalize()方法最终判定对象是否存活,当一个对象被标记为垃圾对象后,如果该对象重写了finalize()方法则不会立刻回收该对象,此时该对象有一次自救的机会,只要重新与引用链上的任何的一个对象建立关联即可。那在第二次标记时它将移除出“即将回收”的集合。如果对象这时候还没逃脱,那基本上它就真的被回收了。
注意:一个对象的finalize()方法只会被执行一次,也就是说通过调用finalize方法自我救命的机会就一次。
finalize()方法的运行代价高昂, 不确定性大, 无法保证各个对象的调用顺序, 如今已被官方明确声明为不推荐使用的语法。
如何判断一个类是无用的类
在进行FullGC回收方法区中的内存时,就需要判断类是不是无用的类,
需要满足下面三个条件才是无用的类:
- 类的实例对象都已经被回收了
- 加载该类的类加载器被回收了
- 堆中该类的java.lang.Class 对象没有在任何地方被引用
相关文章:
java对象的创建与内存分配机制
文章目录对象的创建与内存分配机制对象的创建类加载检查分配内存初始化零值设置对象头指向init方法其他:指针压缩对象内存分配对象在栈上分配对象在Eden区中分配大对象直接分配到老年代长期存活的对象进入老年代对象动态年龄判断老年代空间分配担保机制对象的内存回…...
本地存储localStorage、sessionStorage
目录 一、localStorage 二、sessionStorage 三、本地存储处理复杂数据 一、localStorage 介绍 (1)数据存储在用户浏览器中 (2)设置、读取方便、甚至页面刷新不会丢失数据 (3)容量较大,se…...
JavaSE: 网络编程
1.1 概述java程序员面对统一的网络编程环境B/S 架构 和 C/S架构1.2 网络通信的两个要素通信双方的地址:ip 端口号网络通信协议:TCP/IP协议(事实上的国际规则)、OSI模型(理想化)1.3 Inet Address本地回环地…...
计算机图形学09:二维观察之点的裁剪
作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、二维观察基本…...
2023Java 并发编程面试题
Java 并发编程 1、在 java 中守护线程和本地线程区别? java 中的线程分为两种:守护线程(Daemon)和用户线程(User)。任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(boolon…...
CAD如何绘制A0/A1/A2/A3/A4图框?
在CAD制图时,设计师一般会使用企业的定制图框模板或者个人的特色图框模板,让设计方案更加标准化、规范化。对于新人设计师而言,完成CAD制图已经非常头疼了,图框的绘制更是手忙脚乱。那么是否有更加高效的方式来完成A0、A1、A2、A3…...
R 安装 “umap-learn“ python 包
首先需要在R中下载并读取reticulate包,该包提供了一系列R-Python的交互式命令由于之前在电脑中通过三个方式安装了Python:直接安装 Python 3.10安装Anaconda,携带3.9安装 Miniconda,又是另外一个版本的Python版本各不相同…...
测试同学如何快速开发测试平台?
转眼已经好几个月没有发表什么文章了,因为疫情原因,大家工作都不怎么顺利,没有什么心情。再者,最近一直在搞移动端精准测试的项目,有太多技术难点需要攻克。从各个网站上都找不到解决方案,只能不断地尝试&a…...
【程序员接口百宝箱】免费常用API接口
一、短信发送 短信的应用可以说是非常的广泛了,短信API也是当下非常热门的API~ 短信验证码:可用于登录、注册、找回密码、支付认证等等应用场景。支持三大运营商,3秒可达,99.99%到达率,支持大容量高并发。…...
使数组和能被P整除[同余定理+同余定理变形]
同余定理同余定理变形前言一、使数组和能被P整除二、同余定理变形总结参考资料前言 同余定理非常经典,采用前缀和 map,当两个余数前缀和为一个值时,则中间一段子数组刚好对P整除。但是能否找到前面是否有一段子数组和可以对P整除呐…...
25k的Java开发常问的Synchronized问题有哪些?
前言:面试高频的Synchronized问题大多集中在应用场景、底层实现原理、锁的升级过程。 文章目录 Synchronized定义应用场景对象加锁实现原理JDK6以前JDK6版本及以后对象从无锁到偏向锁转化的过程(大概讲五分钟)轻量级锁升级的过程(大概讲五分钟)自旋锁策略(大概讲五分钟)…...
ES增量同步方案
1 基于业务代码嵌入式的增量同步方式在Java业务代码要修改业务数据的地方,增加调用写入ES数据的方法优点:1、实现方式简单,可控粒度高;2、不依赖第三方数据同步框架;3、数据库不用做特殊配置和部署;缺点&am…...
计算器--课后程序(Python程序开发案例教程-黑马程序员编著-第6章-课后作业)
实例1:计算器 计算器极大地提高了人们进行数字计算的效率与准确性,无论是超市的收银台,还是集市的小摊位,都能够看到计算器的身影。计算器最基本的功能是四则运算。本实例要求编写程序,实现计算器的四则运算功能。 实…...
YOLOv5中添加SE模块详解——原理+代码
目录一、SENet1. 设计原理2. SE Block2.1 Squeeze:Global Information Embedding2.2 Excitation:Adaptive Recalibration3. SE-Inception and SE-ResNet二、YOLOv5中添加SENet1.修改common.py2.修改yolo.py3.修改yolov5s.yaml参考文章一、SENet 论文地址:Squeeze-a…...
arcgispro3.1(账号登陆)
ArcGIS Pro 3.1 更新中文概览专注于 制图、GIS、Python前言:本次更新给了我两个惊喜,一个是本来 ArcMap 就有的功能,另一个明显是学习的 QGIS,嘿嘿,大家往下看吧。整理翻译了一下官方的 ArcGIS Pro 3.1 新特性更新概览…...
VB6换个思路解决微信下载文件只读的问题(含源码)
日期:2023年3月10日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方…...
Allegro如何知道组合操作命令的拼写
Allegro如何知道组合操作命令的拼写 前面介绍了如何知道单个操作命令的拼写,但如果是复合命令,就无法直观的通过命令来了解,如下图 Snap Pick to -Segment这个命令拼写是什么 如何知道,具体操作如下 点击File点击Script 出现Scripting窗口...
CDO高效处理气象数据
基础命令,只需要在终端输入命令按enter运行即可 ####### 查看文件信息 cdo infos xxx.nc #显示nc文件中的变量名 cdo showname sst.nc #读文件夹下的数据 for i in $(ls);do echo processing $i ;done #线性插值 cdo remapbil,经度纬度 input.nc output.nc ;done ##…...
1. Qt Designer Studio界面介绍
1. 说明: Qt当中的Qt Quick框架使用QML语言来快速搭建优美的界面,但是对于单纯做界面的设计人员并不是很友好,还要让界面设计人员去消耗时间成本学习QML语法。Qt Designer Studio软件就是为了解决这个问题而设计的,工作人员不需要…...
elementUI+vue_vue-admin-template框架
目录安装版本管理文件mock文件夹---模拟数据permission.js --- 登录权限控制文件安装 克隆项目git clone https://gitee.com/panjiachen/vue-admin-template.git进入项目目录cd vue-element-admin安装依赖npm install启动服务npm run dev版本管理 由于我们之前的项目是直接从…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
