java对象的创建与内存分配机制
文章目录
- 对象的创建与内存分配机制
- 对象的创建
- 类加载检查
- 分配内存
- 初始化零值
- 设置对象头
- 指向init方法
- 其他:指针压缩
- 对象内存分配
- 对象在栈上分配
- 对象在Eden区中分配
- 大对象直接分配到老年代
- 长期存活的对象进入老年代
- 对象动态年龄判断
- 老年代空间分配担保机制
- 对象的内存回收
- 垃圾标记算法
- 常见的引用类型
- finalize()方法
- 如何判断一个类是无用的类
对象的创建与内存分配机制
对象的创建
java中对象的创建过程如下图所示分为这几步:类加载检查、分配内存、初始化、设置对象头、执行init方法
类加载检查
检查当前要创建对象所对应的类是否被加载过,类元数据信息是否已经在方法区中保存过,如果没有则会去进行类加载的过程,如果加载了则进行下一步
分配内存
这一部分需要考虑两点:
- 应该将哪一块内存区域分配给对象
- 如何解决多个线程并发分配同一块内存问题
如何分配内存
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位机器中的对象头信息
64位机器中的对象头信息
指向init方法
对成员变量赋程序员自定义的值,并调用对象的构造方法
其他:指针压缩
JDK1.6开始,对于64为的机器默认是开启指针压缩的
启用指针压缩:-XX:+UseCompressedOops
(默认开启),禁止指针压缩:-XX:-UseCompressedOops
之所以要使用指针压缩最主要的原因就是节约堆的内存使用
对象内存分配
一个对象的内存分配过程大致如下图所示
对象在栈上分配
我们创建一个对象其实最开始的时候会判断该对象是否能够在栈上分配,目的是减轻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
对象的内存回收
垃圾标记算法
- 引用计数法,对象循环引用问题无法解决
- 可达性分析算法,一般默认使用的这种算法,从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版本管理 由于我们之前的项目是直接从…...
SpringBoot项目使用Schedule注释创建定时任务
文章目录知识讲解相关注释(主要两个,EnableScheduling和Scheduled)scheduled的cron语法代码项目目录结构启动类(Application)定时任务类(Task)配置类(application.properties)pom依赖展望(Quart…...
学习 Python 之 Pygame 开发魂斗罗(十一)
学习 Python 之 Pygame 开发魂斗罗(十一)继续编写魂斗罗1. 改写主类函数中的代码顺序2. 修改玩家初始化3. 显示玩家生命值4. 设置玩家碰到敌人死亡5. 设置敌人子弹击中玩家6. 修改updatePlayerPosition()函数逻辑继续编写魂斗罗 在上次的博客学习 Pytho…...
Linux驱动开发
一、驱动分类Linux中包含三大类驱动:字符设备驱动、块设备驱动和网络设备驱动。其中字符设备驱动是最大的一类驱动,因为字符设备最多,从led到I2C、SPI、音频等都属于字符设备驱动。块设备驱动和网络设备驱动都要比字符设备驱动复杂。因为其比…...
32--Vue-前端开发-Vue语法之组件化开发
一、vue语法回顾 购物车的例子 eg1:计算商品价格(掌握对象的迭代方法) <!DOCTYPE html> <html lang="en"> <head>...
打怪升级之CFileDialog类介绍
CFileDialog类 CFileDialog封装用于文件打开操作或文件保存操作的常见对话框。信息来源自Windows官方文档:https://learn.microsoft.com/zh-cn/cpp/mfc/reference/cfiledialog-class?viewmsvc-170 这里重点介绍几个常用的函数功能: 构造函数 explic…...
配天智造自主原创数字工厂:百余名员工人均创收122万
配天智造(832223)2022年度报告显示,报告期内公司实现营业收入1.3亿元,同比增长52%,归属于挂牌公司股东的净利润3867万元,同比增长28.11%。而这家公司全部在职员工仅有107人,人均创收约为122万。…...
COLMAP
简介:在使用instant-ngp过程中需要使用COLMAP得到模型的必要输入,比如模型需要的相机外参我们就可以通过COLMAP中的sparse reconstruction稀疏重建得到;而对于depth map深度图我们则需要dense reconstruction稠密重建得到,下面我们…...
2023-3-8 刷题情况
礼盒的最大甜蜜度 题目描述 给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。 商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。 返回礼盒的 最大 甜蜜度。…...
关于长连接服务器和客户端之间要加入心跳的一些讨论
在之前的章节里深入浅出TCPIP之深入浅出TCPIP之TCP重传机制 我们都知道了TCPIP协议栈有个默认的TCP心跳机制,这个心跳机制是和socket绑定的,可以对指定的套接字开启协议栈的心跳检测机制。默认情况下,协议栈的心跳机制对socket套接字是关闭的,如果要使用需要人为开启的。 比…...
LeetCode——1590. 使数组和能被 P 整除
一、题目 给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空),使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。 请你返回你需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1…...
福建建设执业资格官网/嘉兴seo外包
文末可以领取所有系列高清 pdf。大家好,我是路人,这是 SpringMVC 系列第 21 篇。本文介绍 Spring web 中特别牛逼的一个类 RestTemplate。目录1、RestTemplate 概述2、案例代码2.1、git 地址2.2、关键代码位置2.3、如何运行测试用例?3、发送 …...
wordpress codecolorer/长沙百度搜索网站排名
手机里使用最多的功能就是APP,现在由于智能手机和网络的大势普及,各行各业的APP也应运而生,一个使用流畅,并且稳定的网络就能使一个APP成功一半了,而使用流畅且稳定有90%都是由服务器来决定的。首先我们要搞明白的一点…...
网站规划建设与管理维护答案/郑州seo方案
先说实现的逻辑(针对操作逻辑对应的事件讲解):onmousedown(鼠标按下事件): 重新获取操作盒子的大小,以及坐标(考虑到客户有可能变更浏览器大小的情况)。获取操作盒子顶部距离获取操作盒子左边距…...
网站建设优化公司排名/深圳全网信息流推广公司
2019独角兽企业重金招聘Python工程师标准>>> objective-c创建对象的两种方法: 1、[类名 new]:直接new一个新对象; 2、[[类名 alloc] init]:先为对象分配内存空间,再为其初始化; 在Co…...
北仑宁波有没有做网站/友情链接交易网
2019独角兽企业重金招聘Python工程师标准>>> 使用php框架CI进行文件上传处理。出现了You did not select a file to upload.的错误提示。翻了一下CI的源码,定位出来是$_FILES获取不到文件信息。继续定位,得知是上传大小受到php本身的限制&…...
网站整体营销方案/百度一下就知道官方网站
第一章 硬件体系结构简介磁盘驱动显示器程序控制数据操纵网络键盘操作系统应用程序驱动器基本输入输出系统(BIOS)中央处理单元(CPU)计算机存储器输入/输出计算机的抽象观察。三个主要要素是:控制和数据处理器,输入输出设备(即I/O器件)以及运行于机器上的…...