Java对象创建和内存分配

news2025/9/17 15:49:08

Java对象创建流程如下步骤

在这里插入图片描述
判断是否加载类
当Java虚拟机执行一条new指令时,首先会检查这个指令的参数是否能在常量池中定位到类的符号引用,并且检查该类是否被加载、验证、准备、解析和初始化过。如果没有则执行加载过程。

给对象分配内存
对象所需的大小在类加载完成后便可以确定,为对象分配内存实际上就是把等同于一个确定大小的内存空间从Java堆中分配出来。

  • 分配内存的两中方式

    • 指针碰撞(Bump the pointer)
      Java堆中的内存是规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,分配内存也就是把指针向空闲空间那边移动一段与内存大小相等的距离。例如:Serial、ParNew等收集器没有产生内存碎片,所以采用的是"指针碰撞"。
    • 空闲列表(Free List)
      Java堆中的内存不是规整的,已使用的内存和空闲的内存相互交错,就没有办法简单的进行指针碰撞了。虚拟机必须维护一张列表,记录哪些内存块是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。例如:CMS这种基于"标记-清除"的收集器,会产生内存碎片,空闲内存跟已经分配的内存相互交错,所以采用的是"空闲列表"。
  • 并发处理
    对象创建在虚拟机中是非常频繁的行为,即使是仅仅修改一个指针指向的位置,在并发情况下也并不是线程安全的,可能出现正在给对象A分配内存,指针还没来得及修改,对象B又同时使用了原来的指针来分配内存的情况。解决这个问题有两种方案:

    • 虚拟机采用CAS加上失败重试的方式保证更新操作的原子性
    • 本地线程分配缓冲(Thread Local Allocation Buffer, TLAB) :把内存分配的动作按照线程划分为在不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存(TLAB)。哪个线程要分配内存,就在哪个线程的TLAB上分配。只有TLAB用完并分配新的TLAB时,才需要同步锁定。可用JVM参数-XX:+/-UseTLAB参数设定。

内存空间初始化
虚拟机将分配到的内存空间都初始化为零值(不包括对象头), 如果使用了TLAB,这一工作过程也可以提前至TLAB分配时进行。
内存空间初始化保证了对象的实例字段在Java代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。

  • 注意:类的成员变量可以不显示地初始化(Java虚拟机都会先自动给它初始化为默认值)。方法中的局部变量如果只负责接收一个表达式的值,可以不初始化,但是参与运算和直接输出等其它情况的局部变量需要初始化。

设置对象头
虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。

执行init()
在上面的工作都完成之后,从虚拟机的角度看,一个新的对象已经产生了。但是从Java程序的角度看,对象的创建才刚刚开始init()方法还没有执行,所有的字段都还是零。
所以,一般来说(由字节码中是否跟随invokespecial指令所决定),执行new指令之后会接着执行init()方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算产生出来。

对象内存分配

基本原则
对象优先在Eden区进行分配
大对象直接进入老年代
长期存活的对象将进入老年代

动态对象年龄判定
HotSpot虚拟机中如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。

空间分配担保
在发生Minor GC之前, 虚拟机必须要检查老年代最大可用的连续空间是否大于新生代所有对象的空间,如果大于, 则此次Minor GC是安全的。如果不大于,则虚拟机会首先查看-XX:HandlePromotionFailure参数的设置值是否允许担保失败;如果允许,那会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,则尝试一次Minor GC;如果小于,或者-XX:HandlePromotionFailure 设置为不允许冒险,那么就会进行一次Full GC。

启动空间分配担保机制是有一定风险的。如果此次是Full GC并启用了空间分配担保机制,因为不清楚将要进入老年代对象的大小,仅能通过以往Full GC 进行评估, 有可能出现一种情况,实际上进入老年代的对象大小要大于老年的可用空间(极端情况是上次内存回收时新生代中所有对象都存活),这样就会出现内存溢出。

注意: 在JDK6 Update24之前,-XX:HandlePromotionFailure需要用户自己设置,之后,虽然虚拟机仍有这个参数,但实际上虚拟机不管有没有设置这个值,都会执行相对的规则:只要老年代的连续空间大于新生代对象总大小或历次晋升的平均大小,就会进行Minor GC,否则将进行Full GC。

逃逸分析(栈内分配)

  • 逃逸分析
    分析对象动态作用域,当一个对象在对象里面被定义后,如果被外部方法引用(列入传参),这是方法逃逸;如果本线程的对象被其它线程访问到,则是线程逃逸。从不逃逸、方法逃逸到线程逃逸被称为对象由低到高的不同逃逸程度。

  • 栈上分配
    一般应用中,完全不会逃逸的局部对象和不会逃逸出线程的对象便可以使用栈上分配,通过随着方法的结束销毁大量的对象可以降低垃圾收集子系统的压力。栈上分配可以支持方法分配,但不支持线程逃逸。

  • 标量替换
    标量: 若一个数据已经无法再分成更小的数据来表示(例如原始数据类型:int,long, reference等),那么这些数据被称为标量。
    聚合量: 如果一个数据可以继续分解,那么这个数据被称为聚合量。
    标量替换: 如果把一个Java对象拆散,根据程序访问的情况,将其用到的成员变量回复为原始类型来访问,整个过程被称为标量替换。

如果逃逸分析证明一个对象不会被方法外部访问,并且这个对象可以被拆散,那么程序真正执行的时候将可能不创建这个对象,而是改为直接创建它的若干各被这个方法使用的成员变量来代替。标量替换可以看成栈上分配的一种特例,实现简单,但对逃逸分析要求高,它不允许对象逃逸出方法范围。

命令
开启逃逸分析:-XX:+DoEscapeAnalysis
查看逃逸分析的分析结果: -XX:+PrintEscapeAnalysis
开启标量替换:-XX:+EliminateAllocations
查看标量替换情况: -XX:+PrintEliminateAllocations

对象内存分配流程图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/520969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生】K8s管理工具--Kubectl(一)

Kubectl管理 一、陈述式管理1、陈述式管理方式2、Kubernetes相关信息查看3、查看节点状态4、命名空间操作5、deployment/pod操作6、扩缩容7、增加删除label 二、声明式管理1、声明式管理方式2、查看资源配置清单3、解释资源配置清单4、修改资源配置清单并应用5、删除资源配置清…

高级篇十三、事务基础知识

第13章_事务基础知识 1、数据库事务概述 事务是数据库区别文件系统的重要特性之一,当我们有了事务会让数据库始终保持一致性,同时我们还能通过事务的机制恢复到某个时间点,这样可以保证已提交到数据库的修改不会因为系统的崩溃而丢失&#…

网络通信-路由交换基础

目录 一、一个简单网络通信(1v1) 二、通信介质 三、交换机通信原理(3v3、5v5) 广播的概念 交换机转发消息时,怎么知道该发给哪个设备 四、路由器通信原理(500v500、5000v5000) 五、消息分…

App Inventor 2 算法之 - 二分算法(Binary Search)实现,快速查找定位

应用介绍 二分算法(Binary Search)是生活中非常常用的折半算法,能解决快速查找、快速定位的问题,主要用到数学和逻辑代码块。 本示例程序演示了采用普通遍历的方式和二分的方式分别需要几次能够猜中随机给出的数字。 二分算法&a…

k8s-CKS真题-故障排查Sysdig falco

目录 题目环境搭建安装sysdig创建容器创建目录、文件 解题 - sysdig解题 - falco错误模拟环境参考 题目 Task: 使用运行时检测工具来检测 Pod tomcat123 单个容器中频发生成和执行的异常进程。 有两种工具可供使用:sysdigfalco注:这些工具只…

如何有效提高企业优秀人才的留存率?

对于企业而言,有效的员工入职流程应是一个持续的项目。优秀人才使企业持续性发展的基石,那么该如何提高企业优秀人才的留存率呢? 有调查显示新员工入职后短时间内离职的比率日益上升,因此做好员工入职,短时间内增加员工…

msvcp140.dll是什么东西

昨天在打开photoshop软件的时候,突然间就提示msvcp140.dll丢失,无法打开运行。msvcp140.dll是什么东西呢?今天早上用了一个上午的时间,特意搞清楚了msvcp140.dll是什么以及如何修复电脑msvcp140.dll文件丢失问题。下面小编就把整理…

八年软件测试感悟--写给还在迷茫的你

不知不觉已经从事软件测试八年了,2015毕业到进入外包公司外包给微软做软件测试, 到现在加入著名的外企。八年的时间过得真快。 长期的测试工作也让我对软件测试有了比较深入的认识。但是我至今还是一个底层的测试人员,我的看法都比较狭隘&…

热乎的面经——水滴石穿

⭐️前言⭐️ 本文记录博主面试北京某大厂所记录的面经,回答答案仅供参考。 🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言 …

公网SSH远程访问家中的树莓派[无公网IP]

文章目录 前言如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地址…

计算机视觉的深度学习 Lecture4:Regularization + Optimization 笔记 EECS 498.008

课件非常好! 数值计算梯度 问题是慢,每个都要注意做步长,求除法。 应该用求导方法解决。 SGD通过每次抽取一部分(mini-batch)来计算梯度,而不是遍历整个数据集来求梯度,大大增大了求梯度速…

18 KVM管理虚拟机-虚拟机生命周期总体介绍

文章目录 18 KVM管理虚拟机-虚拟机生命周期总体介绍18.1 概述18.2 虚拟机状态18.3 状态转换18.4 虚拟机标识 18 KVM管理虚拟机-虚拟机生命周期总体介绍 18.1 概述 为了更好地利用硬件资源,降低成本,用户需要合理地管理虚拟机。本节介绍虚拟机生命周期过…

零基础学网络安全

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了.2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发.3.有时多 google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答.4.遇到实在搞不懂的,可以先放放,以后再来解决. 一…

spring的事物

这是我第三次接触事物了,mysql一次,以前的也看过一次。 事物的四大特点: 原子性:多条sql保证同时成功,同时失败。 一致性:在事物的开启和结束,数据库的完整性不被破坏。 隔离性:多线…

centos7 配置密钥登录

目录 1.xshell生成公钥 1.工具->新建用户密钥生成导向 2.选择4096下一步​编辑 3.输入用户密钥密码,也可以不输入 4.保存为文件 5.导出私钥文件 2.服务器配置 1.将公钥文件上传至服务器上 3.链接服务器 1.新建连接配置ip 2.设置用户身份验证 3.选择1.5上…

大疆无人机空三建模干货分享(大疆智图集群建模超详细教程)

Part 01 大疆无人机空三建模干货分享(大疆智图集群建模超详细教程) 大疆智图集群简介 大疆在今年5月推出的智图3.0.0及以上版本中加入了集群功能,有集群版许可的用户可以使用此功能。智图集群是由一台主节点分配任务控制多台同局域网内子节点设备进行空三和建模。集…

【Java零基础入门篇】第 ④ 期 - 继承(三)

【Java零基础入门篇】第 ④ 期 - 继承(三) 博主:命运之光专栏:Java零基础入门 学习目标 1.掌握继承性的主要作用、实现、使用限制; 2.掌握this和super的含义及其用法; 3.掌握方法覆写的操作; 4.…

内网渗透(七十)之域权限维持之重置DSRM密码

重置DSRM密码 目录服务还原模式(DSRM)是Windows域环境中域控的安全模式启动选项。每个域控都有一个本地管理员administrator账户,也就是(DSRM账户)。DSRM的用途是允许管理员在域环境出现故障或崩溃时还原、修复、重建活动目录数据库,使域环境的运行恢复正常。也就是说,DS…

关于安卓毛玻璃实现(三)recyclerview静态毛玻璃

背景 毛玻璃,开发中又爱又恨的一个话题,玩法层出不穷,有动态的,也有静态的。有的是实时模糊,有些只需要模糊一次,本文的毛玻璃实现,就是静态毛玻璃。 开发环境 win 10 as 4 jdk 1.8 代码 &…

在中国,年收入20W是什么水平?答案扎心了(文末附最新招聘)

最近关于“年薪20万算什么水平?”冲上了热搜。对此,许多网友纷纷表示自己的看法,有的认为这个收入属于中高收入人群了。 因为按照最近某招聘网站发布的《中国企业招聘薪酬报告》来看,今年一季度38城企业平均招聘薪酬为10101元&…