当前位置: 首页 > news >正文

JVM对象创建与内存分配机制

对象创建过程:

一:是否加载

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
new指令对应到语言层面上讲是,new关键词、对象克隆、对象序列化等

二:分配内存

如何分配?

指针碰撞(默认)

如果内存是规整了,所有用过的内存在一边,空闲的在另一边,中间放着一个指针作为分界点指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。

空闲列表

如果内存不规整,就必须维护一个列表,记录哪些内存可用,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录。

并发情况怎么处理?

cas 

TLAB(Thread Local Allocation Buffer)本地线程分配缓存,8版本默认开启,JVM参数可以控制 -XX:+/UseTLAB大,-XX:TLABSize 小为伊甸园区的1%如果放不下,就走cas

三: 初始化

四:设置对象头

对象填充的作用? 保证对象是8字节的倍数,对象寻址效率最高的方式,计算机原理定义的。

对象指针表示的是?-XX:+UseCompressedOops(默认开启)

对象指针用到了指针压缩(小于等于32G),那么什么是指针压缩? 节约内存空间 , 32位的操作系统只能表示4g内存,我们平时工作的都是8G以上的也就是2的33次方或者更多,指针压缩就是通过算法,把超出来的变成32的,通过他找对象的时候,又变成实际的来找,节约内存资源,因此堆内存尽量建议不要超过32G. 否则会用8位来存储寻址,导致带宽加大,同时GC也会有较大压力

堆内存小于4G时,不需要启用指针压缩,jvm会直接去除高32位地址,即使用低虚拟地址空间
堆内存大于32G时,压缩指针会失效,会强制使用64位(即8字节)来对java对象寻址,这就会出现1的问题,所以
堆内存不要大于32G为好

五:执行init方法

给对象赋值和调用构造方法

整个分配过程涉及到的知识点:

对象逃逸分析?

减少gc压力,把不逃逸的分配到栈的栈帧里(默认128k?兆) 例如void方法

jdk7默认开始,-XX:+DoEscapeAnalysis(+开启-关闭)

标量替换? 

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

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

栈上分配依赖: 逃逸分析和标量替换

对象在内存中的分配流程?

大对象直接进入老年代, 防止在幸存者区来回复制移动

长期存活的对象进入老年代 --XX:MaxTenuringThreshold参数来设置多大年龄进入

伊甸园区的比例是否开启(8:1:1),开启参数,默认为自适应

对象动态年龄判断机制: 会导致1秒就称为垃圾的系统存入老年代

大对象一般怎么处理?

JVM参数 -XX:PretenureSizeThreshold (单位字节)可以设置对象的大小,超过这个设置的会直接进入老年代,这个参数只在Serial和ParNew两个收集器下有效。

比如设置JVM参数:-XX:PretenureSizeThreshold=1000000 (单位是字节) -XX:+UseSerialGC 代码执行会发现大对象直接进了老年代

这样做的目的:减少为大对象分配内存时的复制操作而降低效率。

长期存活对象进入老年代:

-XX:MaxTenuringThreshold可以设置值,默认为15岁,CMS收集器默认6岁,不同的垃圾收集器会略微有点不同。不超过15的原因是记录年龄的这块分配了4bit位置

对象动态年龄判断?

当前放对象的Survivor区域里,一批对象的总大小大于Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定),那么此时大于等于这批对象年龄最大值的对象,就会直接进入老年代里。会引起GC。 对象动态年龄判断机制一般是在minor gc之后触发的。
这个规则其实是希望哪些尽可能长的对象尽早的进入老年代

老年代空间分配担保机制?

-XX:-HandlePromotionFailure 在java8默认开启了
在minor gc前判断 老年代剩余空间是否大于等于 年轻代里所有的对象(包含垃圾) ;
如果大于就minor gc回收;如果不足继续:
如果没开启,直接Fullgc 然后在 minor gc 
如果开启了这个机制,会再次判断,剩余空间是否>=历届minor gc回收后剩余的值, 如果满足,minor gc 否则直接Fullgc 然后在 minor gc ;
总的来说是一种优化。

为什么元空间不怎么能回收到垃圾(无用类)?

条件苛刻,基本上只有热部署的像tomcat那种的才会被回收,需要满足以下条件:

1.类所有的实例已经被回收,即java堆中没有该类的任何实例。

2.加载该类的ClassLoader已经被回收

3.该类对应的java.lang.Class对象已经没有任何地方饮用了,无法在任何地方通过反射访问该方法。

http://www.dtcms.com/a/291471.html

相关文章:

  • 上海RISC-V峰会-香山开源RISC-V CPU随想随记
  • Golang在Web开发中的应用
  • 设备虚拟化
  • hard_err错误
  • 50-字母异位词分组
  • SmartETL循环流程的设计与应用
  • 外辐射源入门综述
  • 板凳-------Mysql cookbook学习 (十二--------4)
  • c++找工作(qt)
  • 【金仓数据库产品体验官】_KingbaseES(SQLServer兼容版)保姆级安装教程
  • LiteCoT:难度感知的推理链压缩与高效蒸馏框架
  • 【CNN】卷积神经网络多通道卷积与偏置过程- part2
  • AI Red Teaming 分析
  • 鸿蒙开发中与 AI 编码助手的共处之道(ArkTS 视角)
  • sky-take-out项目中Redis的使用
  • 【每日算法】专题十七_多源 BFS
  • Java 实现 UDP 多发多收通信
  • 图论(2):最短路
  • http协议学习-body各种类型
  • cs336 Lecture2
  • SQL基础入门② | 运算符篇
  • 【HarmonyOS】ArkTS语法详细解析
  • 阿里云技术三面:java社招面经+面试题分享!
  • rancher使用rke在华为云多网卡的服务器上安装k8s集群问题处理
  • Supervisor 核心原理:如何实现进程管理?
  • 机器视觉的食品包装贴标应用
  • [论文阅读] 人工智能 | ZipMPC:让短视的MPC拥有长远眼光——通过模仿学习压缩长 horizon 智慧
  • A1-静态Mpls
  • 二、计算机网络技术——第2章:物理层
  • [1-01-01].第90节:如何学习新特性: