JVM-【面试题】-对象内存分配

news2025/2/22 16:12:46

一、对象内存分配流程图

  1. 如果能在栈分布就直接在栈创建

  1. 如果是大对象就直接在old区创建

  1. 如果不大于TLAB则在TLAB创建,否则在Eden区创建

  1. 如果Eden区空间不足就会发生Minor GC进行回收,回收的空间放不下或年龄达到上限就直接放到Old区,之后S0区的存活对象移动到S1区。然后对S0区清理,清理完毕原S0区变成S1区,原S1区变成S0区。

二、对象在栈上分配

在JVM中,堆是线程共享的,因此堆上的对象对于各个线程都是共享和可见的,只要持有对象的引用,就可以访问堆中存储的对象数据。虚拟机的垃圾收集系统可以回收堆中不再使用的对象,但对于垃圾收集器来说,无论筛选可回收对象,还是回收和整理内存都需要耗费时间。

为了减少临时对象在堆内分配的数量,JVM通过逃逸分析确定该对象不会被外部访问。如果不会逃逸可以将这个对象分配在栈上分配内存,这样,对象所占用的内存空间就可以随栈帧出栈而销毁。在一般应用中,不会逃逸的局部对象所占的比例很大,如果能使用栈上分配,那大量的对象就会随着方法的结束而自动销毁了,无须通过垃圾收集器回收,可以减小垃圾收集器的负载。

JVM允许将线程私有的对象打散分配在栈上,而不是分配在堆上。分配在栈上的好处是可以在函数调用结束后自行销毁,而不需要垃圾回收器的介入,从而提高系统性能。

对象逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中。

public Order test1() {
   Order order = new Order();
   order.setId(1);

   //其他业务代码
   return order;
}

public void test2() {
   Order user = new Order();
   order.setId(1);
 
   //其他业务代码
}

test1方法中的Order对象被返回了,表明这个对象的作用域范围是不确定的。

test2方法中的Order对象我们可以确认当方法结束后这个对象就是无效对象,这样的对象是可以将其分配在栈内存里的,让其在方法结束时随着栈内存一起被回收掉。

JVM对于这种情况可以通过开启逃逸分析参数-XX:+DoEscapeAnalysis来优化对象内存分配位置,使其通过标量替换优先分配在栈上(栈上分配),JDK7之后默认开启逃逸分析,如果要关闭使用参数-XX:-DoEscapeAnalysis

标量替换:通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而是将该对象成员变量分解若干个被这个方法使用的成员变量所代替,这些代替的成员变量在栈帧或寄存器上分配空间,这样就不会因为没有一大块连续空间导致对象内存不够分配。开启标量替换参数-XX:+EliminateAllocationsJDK7之后默认开启

标量与聚合量:标量即不可被进一步分解的量,而JAVA的基本数据类型就是标量(如:int,long等基本数据类型以及reference类型等),标量的对立就是可以被进一步分解的量,而这种量称之为聚合量。而在JAVA中对象就是可以被进一步分解的聚合量。

三、对象在Eden区分配

大多数情况下,对象在新生代中Eden区分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC进行垃圾回收。

在JVM里Eden与Survivor区默认8:1:1

大量的对象被分配在eden区,eden区满了后会触发minor gc,可能会有99%以上的对象成为垃圾被回收掉,剩余存活的对象会被挪到为空的那块survivor区,下一次eden区满了后又会触发minor gc,把eden区和survivor区垃圾对象回收,把剩余存活的对象一次性挪动到另外一块为空的survivor区,如果

survivor区存放不下,会把新生代的对象提前转移到老年代里。

新生代的对象都是朝生夕死的,存活时间很短,所以JVM默认的8:1:1的比例是很合适的,让eden区尽量的大,survivor区够用即可。

JVM默认有这个参数-XX:+UseAdaptiveSizePolicy(默认开启),会导致这个8:1:1比例自动变化,如果不想这个比例有变化可以设置参数-XX:-UseAdaptiveSizePolicy

四、大对象进入老年代

大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。

JVM参数 -XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 SerialParNew两个收集器下有效。

这样的好处是在于为了避免为大对象分配内存时的复制操作而降低效率。

五、长期存活的对象将进入老年代

虚拟机给每个对象一个对象年龄(Age)计数器,在内存回收时就必须能识别哪些对象应放在新生代,哪些对象应放在老年代中。

如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为1。对象在 Survivor 中每熬过一次 MinorGC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁CMS收集器默认6岁,不同的垃圾收集器会略微有点不同),就会被晋升到老年代中。

对象晋升到老年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。

六、对象动态年龄判断

当前放对象的Survivor区域里(其中一块区域,放对象的那块s区),一批对象的总大小大于这块Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定),那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代了,例如Survivor区域里现在有一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把大于50%的年龄n(含)以上的对象都放入老年代。这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。对象动态年龄判断机制一般是在minor gc之后触发的。

七、老年代空间分配担保机制

  1. 年轻代每次minor gc之前JVM都会计算下老年代剩余可用空间

  1. 如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象)

  1. 就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了

  1. 如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次minor gc后进入老年代的对象的平均大小

  1. 如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full gc,对老年代和年轻代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生"OOM"

  1. 当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可用空间,那么也会触发full gc,full gc完之后如果还是没有空间放minor gc之后的存活对象,则也会发生“OOM”

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

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

相关文章

Vue3.0 性能提升主要是通过哪几方面体现的?

一、编译阶段 回顾Vue2,每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把用到的数据property记录为依赖,当依赖发生改变,触发setter,则会通知watcher,从而使关联的组件重新渲染 试想一下&…

34420A万用表

18320918653 34420A Agilent 34420A 七位半台式数字万用表|安捷伦纳伏表34420A|微欧表|安捷伦34420A 品牌: Agilent(安捷伦) 1.3nV rms噪声/8n Vp-p 100pV,100nΩ灵敏度 两通道可编程电压输入:差分和比值功能 71/2位分辨率 1mV到100V量程…

如何通过指令控制将一副扑克牌变成一种简单的计算机

题目 题目就是文章的标题 已知 牌数:每套扑克牌有54张,其中去掉大小王,剩下52张,这52张中又有4种花色黑桃,红桃,梅花,方片每种花色都有13张(1,2,3,4,5,6,7,8,9,10,J,Q,K&#xff…

【Ubuntu】在VMWare虚拟机中安装Ubuntu【教程】

文章目录【Ubuntu】在VMWare虚拟机中安装Ubuntu教程一、安装VMWare二、下载Ubuntu的iso文件三、安装UbuntuReference【Ubuntu】在VMWare虚拟机中安装Ubuntu教程 一、安装VMWare 具体的安装方法,可以参考这一篇博客,这里就不详细介绍了 二、下载Ubuntu…

centos禁止root登录

ssh登录linux服务器的时候,经常会有提示 There were * failed login attempts since the last successful login. 说明有大量的非法登录尝试 检查服务器是否被恶意登录 # Ubuntu # 1. 查看近期成功的密码登录: grep "password" /var/log/au…

如何搭建邮箱服务器?mail系统架设的两种方法

邮件mail通信是常用的办公场景,对于技术和网管等人员,往往需要搭建自己的邮箱服务器。那么,如何架设邮箱系统呢?通常有两种方案,一种是在在本地主机部署,另一种是在云端如云服务器上部署应用。根据主机IP情…

以交互方式导入图像、音频和视频

以交互方式将数据导入到 MATLAB 工作区。 查看文件的内容 指定变量 生成可重用的 MATLAB 代码 注意:​有关导入文本文件的信息,可以参考使用导入工具读取文本文件数据。有关导入电子表格的信息,可以参考使用导入工具读取电子表格数据。 查…

【Redis数据对象与结构】string与其底层结构

【Redis数据对象与结构】string与其底层结构 【Redis数据对象与结构】系列的主线如下,本文主要讲解string数据对象及其底层结构在redis中的实现。 redis中基本的数据对象有字符串类型(String)、列表类型(List)、字典类型(Hash)、集合类型(Set)、有序列表类型(Sorte…

自定义类型之枚举与联合

文章目录前言一、枚举1.枚举的定义2.枚举的几种情况3.枚举类型的大小4.枚举的优点二、联合(共用体)1.联合类型的定义2.联合的特点3.联合的大小计算总结前言 自定义类型很多人可能只知道结构体,因为结构体相对来说确实用的比较多,而…

爬虫攻守道 - 2023最新 - 正则表达式勇猛精进 - 爬取某天气网站历史数据

前言 在 正则表达式 - 匹配开头、结尾、中间 - 某天气网站网页源代码分析 这篇文章里,我们介绍了如何用正则表达式匹配包含特定样式的Table标签,也就是同时匹配开头、结尾、以及中间。 当你能真正理解这个写法,就会觉得不过是柳暗花明罢了。…

如何把拍摄视频中多余的人或物去除?

大家应该都有这样一个烦恼吧?就是拍摄的一段视频中有多余的人物出现,想要把里面的人物去除掉,或者是自己拍摄的一段视频,视频里出现了多余的人物,但是又不能重启拍摄的情况下,想要把视频中的人物去除掉应该…

Spring Security笔记

创建个项目 引入Spring Web和Spring Security 即可 写个Controller接收请求 转发重定向都可以 static下定义两个页面 login.html页面 用来登录 main.html如果可以跳到这里,说明登录成功 启动运行程序 我们访问登录接口 或者是访问静态资源都会重定向到这个页面 这个页面说…

并发编程(多线程)

一、进程与线程 多进程编程已经能够解决并发编程的问题了(已经可以利用cpu多核资源了).但是仍然存在这缺陷. 就是,进程太重了(消耗资源多,速度慢),线程应运而生被称为"轻量级编程",解决并发编程的各种问题的同时,让IO速度大大提升. 线程"轻"主要"轻…

SOFAEnclave:蚂蚁金服新一代可信编程环境,让机密计算为金融业务保驾护航102年

引言 互联网金融本质上是对大量敏感数据的处理以及由此沉淀的关键业务智能。近年来涌现出来的新业态更是将数据处理的范畴从单方数据扩展到了涉及合作方的多方数据。 另一方面,从 GDPR 到 HIPAA,数据隐私监管保护的范围愈加扩大,力度日益增…

app逆向 || x动

声明 本文仅供学习参考,如有侵权可私信本人删除,请勿用于其他途径,违者后果自负! 如果觉得文章对你有所帮助,可以给博主点击关注和收藏哦! 本文适用于对安卓开发和Java有了解的同学! 文中涉及的app均放在…

运行Dlinknet提取道路和水体(总结帖)——全流程步骤总结

之前写了很多制作样本然后跑代码的帖子 但由于我也是第一次跑 记录一下自己摸索的过程 因此导致 每一篇的内容很碎 每次我想自己去回顾一下的时候 都有太多摸索尝试的过程了 因此我在这里总结一下我摸索的整个过程的详细步骤 大家可以先看这篇再去我的对应博客里面看具体的细节…

【C++逆向】虚表(Virtual table)

什么是多态 定义一个虚基类ISpeaker class ISpeaker{ protected:size_t b; public:ISpeaker( size_t _v ): b(_v) {}virtual void speak() 0; };有两个子类,都实现了虚函数speak(): class Dog : public ISpeaker { public:Dog(): ISpeaker(0){}//vir…

Gin操作MySQLd的增加修改删除的Restful风格的API

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文 目录 一、gin是什么? 二、gin- mysql 1.gin-mysql 2.CRUD的gin的mysql 通过jsontool

Win10忘记开机密码无法进入桌面怎么办?

Win10忘记开机密码无法进入桌面怎么办?有用户设置了电脑的开机密码之后,因为一段时间没有去开机使用电脑了,导致将开机的密码忘记了。那么这个情况下我们怎么去进行电脑的开机呢?接下来我们来看看详细的解决方法分享吧。 解决方法…

SpringCore RCE 1day漏洞复现(NSSCTF Spring Core RCE)

漏洞描述: 作为目前全球最受欢迎的Java轻量级开源框架,Spring允许开发人员专注于业务逻辑,简化Java企业级应用的开发周期。 但在Spring框架的JDK9版本(及以上版本)中,远程攻击者可在满足特定条件的基础上,通过框架的…