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

news2024/11/25 3:02:51

1. JVM对象创建过程详解

对象创建的主要流程

在这里插入图片描述

1.1 分配内存空间的方法

  1. 指针碰撞(默认使用指针碰撞) 如果JAVA堆中内存是绝对规整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放一个指针作为分界点,那么所分配的内存就仅仅是把的那个指针向空闲空间移动一段与对象大小相等的距离
  2. 空闲列表 如果JAVA堆中内存是不规整的,已使用的内存和空闲的内存相互交错,那就没有办法简单的指针碰撞了,虚拟机就必须维护一个列表,记录上那些内存块是可用的,再分配的时候从列表中找出一块足够大的空间分配给对象实例,并更新列表的记录

根据垃圾收集器的不一样,分配的内存方法略有不同
但是不管是那种分配方式,都会存在并发问题

解决并发问题的方法

  • CAS(compare and swap)
    虚拟机采用CAS配上失败重试的方式保证更新操作的原子性来对内存空间的动作进行同步处理
  • 本地线程分配缓冲(Thread Local Allocation Buffer ,TLAB)
    把内存分配的动作按照线程划分在不同的空间中进行,即每个线程在Java堆中预先分配一小块内存,通过-XX:+/- UseTLAB参数来设定虚拟机是否使用

1.2初始化

相当于给静态变量等等一些列的方法赋予一个初值例如int i 默认初始化0 对象初始化null 等等

1.3设置对象头

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

  • hotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头、实例数据、对齐填充
  • 下面是对象头的数据
    在这里插入图片描述
  1. markWord标记字段(32位占4字节,64位占8字节)里面存放着自身运行时的数据:hash值,GC分代年龄等等
  2. Klass Pointer类型指针(开启压缩占4字节,关闭占8字节)这个Klass Pointer是干嘛用的呢,这里解释一下首先他是在堆里面,其次他指向了我们方法区里面的类元信息,这样我们就知道我们是哪个对象的实例了(个人理解)
  3. 数组长度(4字节,只有数组对象才有)

这里让我们来看看对象里面的具体数据
这里先导入依赖

       <dependency>
            <groupId>org.openjdk.jol</groupId>
             <artifactId>jol‐core</artifactId>
             <version>0.9</version>
        </dependency>

编写代码

package com.ruoyi.framework.com.qin;

import org.openjdk.jol.info.ClassLayout;

public class TestClassHeader {

    public static void main(String[] args) {

        ClassLayout classLayout = ClassLayout.parseInstance(new Object());
        System.out.println(classLayout.toPrintable());
        System.out.println();

        ClassLayout classIn = ClassLayout.parseInstance(new int[]{});
        System.out.println(classIn.toPrintable());
        System.out.println();

        ClassLayout classA = ClassLayout.parseInstance(new A());
        System.out.println(classA.toPrintable());
        System.out.println();

    }

    public static class A{
        int id;
        String name;
        Object o ;
    }

}

下面是结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对象对齐

1.4 init方法

设置完对象头,按照程序员的意愿来赋值

2. 对象内存分配流程图

在这里插入图片描述
以前一般情况下我们是分配在堆里面的,后来慢慢地我们不一定了

这里有个比方 有两段代码
在这里插入图片描述
假如现在调用了test1()方法,返回了user,说明这个user是逃逸了,在其他地方是有用到的,下一个test2其实这个方法的user对象就只在当前方法下有用,说明没有逃逸,那么为什么我们不把他放在栈里面跟着方法执行完毕就把他释放掉,而要放在堆里面等待垃圾回收

jvm里面提供了一个方法,一般情况下默认开启了逃逸分析来优化内存,并且逃逸分析和标量替换会同时开启

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

在这里插入图片描述

刚刚讲的是放在栈上面的如果是放在对上面的呢?

这里有个一例子
在这里插入图片描述
假设Eden区的内存大小为65536k s0区10752k s1区10752k 老年代175104k 那么

  • 如果只是单独执行这个application1是放在eden区的
  • 如果执行了application1和application2那么application1是放入老年代的,application2是放在Eden区的,为什么呢?首先这两块地方的内存大小已经超过了Eden区,如果放在s0区,s0区明显放不下,那么这个application1只能放在老年代
  • 如果执行了所有那么,application1放在老年代,其他的全部放在Eden区

那这个如果我们想要减少垃圾回收,由于老年代比年轻代大得多,大对象我们是不是可以放入老年代呢,大对象就是需要大量连续空间的对象,(比如字符串、数组等等),那么JVM这里提供了一个参数 -XX:PretenureSizeThreshold可以直接设置大对象直接进入老年代,不会进入年轻代,这个参数只在Serial和ParNew两个收集器下有效哦

在这里插入图片描述

  • 为什么要这样呢
    避免了大对象分配内存的时候复制操作而降低效率,并且在一定程度上可以减轻minorJc

这里有一个机制:对象动态年龄判断机制,如果一批对象大于这块Survicor区域内存大小的50%,会直接进入老年代。例如Survivor区域里出现了一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor的区域的50%,此时会把年龄n和n以上的对象都放入老年代。这个规则其实是希望那些可以长期存活的对象,尽早进入老年代

老年代空间担保机制

在这里插入图片描述

3. 对象回收机制

就是gc垃圾回收,是如何回收的,这里一般用的是可达性分析算法,还有一个引用计数器算法但是一般不用,当发生相互引用的情况下这个算法会出现问题,相当于内存泄漏

可达性分析算法里面有一个finalize()方法,这个方法继承Object
在这里插入图片描述
当垃圾收集器准备回收这个类的实例的时候,就会执行这个方法,我们可以在这里建立与其他对象的连接,例如把自己的赋值给某个类或者变量挥着对象的成员变量。那在第二次标记清除的时候会将他移除即将回收的集合。如果这个对象还是没能逃脱,那么基本上他就真的被回收了

注意:一个对象的finalize()方法只会被执行一次,也就是通过调用finalize方法自我救命的机会只有一次

  • 如何判断一个类是无用的类呢
  • 方法区主要回收的是无用的类,那么怎么才是无用的类呢?
  1. 该类的所有对象实例都被回收,也就是java堆中不存在该类的任何实例,这就是说明堆里面不会再有对象头被引用
  2. 加载该类的ClassLoader已经被回收,每个ClassLoader都会维护一个他自己加载类的集合(这个条件挺苛刻的)那么就说明会app、ext、boot三类类加载器加载的类几乎很难被回收掉,这里说明其实你做了fullgc,其实也很难释放一定的空间
  3. 该类的java.lang.Class对象没有被任何地方引用,无法在任何地方通过反射来访问该类

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

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

相关文章

Tableau长期免费使用的方法总结

目录方法一&#xff1a;使用Tableau Public第一步&#xff1a;在Product中点击Tableau Public第二步&#xff1a;向下滚动找到下载链接第三步&#xff1a;进入下载页面点击下载方法二&#xff1a;每一个可下载版本滚动试用14天第一步&#xff1a;**resource** → **support** →…

06【SpringMVC的Restful支持】

文章目录六、SpringMVC的Restful支持6.1 RESTFUL示例&#xff1a;6.2 基于restful风格的url6.3 基于Rest风格的方法6.4 配置HiddenHttpMethodFilter6.5 Restful相关注解六、SpringMVC的Restful支持 REST&#xff08;英文&#xff1a;Representational State Transfer&#xff…

.vcxproj.filters 误删后如何重建

背景&#xff1a; 今天碰到这样一种情况&#xff0c;我在删除这个VS文件夹下的.user文件时&#xff0c;不小心把.vcxproj.filters也删除了。当然为什么删.user呢&#xff0c;因为换电脑了。 删除之后&#xff0c;我发现&#xff1a;我的解决方案目录变成这样了&#xff1a; 对…

基于springboot企业客户信息反馈平台设计与实现的源码+文档

摘 要 网络的广泛应用给生活带来了十分的便利。所以把企业客户信息反馈管理与现在网络相结合&#xff0c;利用java技术建设企业客户信息反馈平台&#xff0c;实现企业客户信息反馈的信息化。则对于进一步提高企业客户信息反馈管理发展&#xff0c;丰富企业客户信息反馈管理经…

数据分析:从界定问题开始做数据分析?

一、引言 “界定问题”是数据分析工作流程的第一步,也是最重要的一步。再怎么强调“界定问题”的重要性都不为过,因为一旦没有把问题界定清楚,后续的工作很可能将会南辕北辙。而如果我们将问题界定清楚,就能针对性的制定解决方案。 1.什么是界定问题 界定问题是一个需求…

黄健翔质疑半自动越位技术?用「技术流」解读卡塔尔世界杯

昨天&#xff0c;喀麦隆3比3塞尔维亚的比赛&#xff0c;黄健翔发微博质疑「半自动越位识别技术」太慢&#xff0c;而且没有考虑观众的需求&#xff0c;严重影响看球的体验&#xff0c;巴西和瑞士的比赛&#xff0c;黄健翔连发三条微博&#xff0c;再次吐槽VAR技术对足球带来的伤…

Qt | QTextCodec类使用详解、GBK和UTF8编码互转、QString的toLocal8bit和toLatin1区别

Qt | QTextCodec类使用详解、GBK和UTF8编码互转、QString的toLocal8bit和toLatin1区别 目录Qt | QTextCodec类使用详解、GBK和UTF8编码互转、QString的toLocal8bit和toLatin1区别1、QTextCodec简介及使用1.1 编码之间的转换1.2 解决中文显示乱码问题2、QString的toLocal8bit和t…

Python——基本数据类型的转换

1、为什么需要左数据类型的转换 2、转换为整形&#xff1a; 浮点类型转换为整形&#xff1a; a 3.14 b int(a) print(b) 浮点类型转换成整形的规则是&#xff1a;保留小数点前面的数&#xff0c;去掉小数点和小数点后面的数。 字符串转换成整形&#xff1b; a 123 b int(a…

PHP怎么实现实时聊天?GatewayWorker+Thinkphp5即时通讯系统实现

PHP怎么实现实时聊天&#xff1f;GatewayWorkerThinkphp5即时通讯系统实现 一、项目介绍 后端技术&#xff1a;thinkphp5fastadmingatewayworker 前端技术&#xff1a;jqueryhtmlcsswebsocket 项目实现了简单的登录、注册功能&#xff0c;会员可进行后台管理&#xff0c;主界…

[OpenCV实战]52 在OpenCV中使用颜色直方图

颜色直方图是一种常见的图像特征&#xff0c;顾名思义颜色直方图就是用来反映图像颜色组成分布的直方图。颜色直方图的横轴表示像素值或像素值范围&#xff0c;纵轴表示该像素值范围内像素点的个数或出现频率。颜色直方图属于计算机视觉中的基础概念&#xff0c;其常常被应用于…

Ceres库中参数理解

1 参数含义 2 参考链接 Modeling Non-linear Least Squares — Ceres Solver (ceres-solver.org) Ceres详解&#xff08;二&#xff09; CostFunction_他人是一面镜子&#xff0c;保持谦虚的态度的博客-程序员宝宝_ceres costfunction - 程序员宝宝 (cxybb.com)

Linux基础知识与实操-篇七:用户身份切换与特殊控制

文章目录使用者身份的切换配置sudo单一用户群组处理有限制的命令操作特殊shell与PAM模块Linux用户信息传递与当前系统上其他用户对话建立大量账号最后在理解了前篇 篇六:用户权限控制与账号管理 后&#xff0c;我们继续深入用户权限控制关于用户身份切换、限制特殊权限相关的内…

一步步带你用react+spring boot搭建后台之二(登录与首页篇)

前言 最近半年一直在重庆忙于项目上的事情&#xff0c;博客停更了好久&#xff0c;一直想写2个开源项目: 一个是入门级&#xff1a;一步步带你用reactspring boot搭建后台 一个是olap应用系列&#xff1a;一步步构建olap分析平台 今天开始写第一个系列&#xff0c;完整代码随…

LDO(线性稳压器)设计检查

原理图设计规范检查——LDO&#xff08;线性稳压器&#xff09;设计检查 LDO基本概念&#xff1a; LDO即low dropout regulator&#xff0c;是一种低压差线性稳压器&#xff0c;这是相对于传统的线性稳压器来说的。传统的线性稳压器&#xff0c;如78XX系列的芯片都要求输入电…

Linux cifs挂载远程windows共享目录

Linux cifs挂载远程windows共享目录共享windows目录开启共享权限共享磁盘或目录Linux 先决条件安装Linux依赖开启Administrator 用户使用Username/Password挂载临时挂载自动挂载使用Credentials挂载创建CIFS Windows共享凭证文件临时挂载自动挂载终止挂载共享windows目录 开启…

“算力时代”奔涌而来,JASMINER茉莉发布能效更强劲的X16-Q

11月26日&#xff0c;JASMINER茉莉发布X16系列首款静音型算力产品X16-Q&#xff0c;并同步开启全球预售&#xff0c;将为行业带来更高效、更绿色、更智能的智慧算力。 JASMINER X16相较X4系列产品迎来了全新的“进化”&#xff0c;除去新一代JASMINER茉莉自研高通量芯片的应用…

百看不如一练系列 32个python实战项目列表,得不到就毁掉

前言&#xff1a; 不管学习哪门语言都希望能做出实际的东西来&#xff0c;这个实际的东西当然就是项目啦&#xff0c;不用多说大家都知道学编程语言一定要做项目才行。 这里整理了32个Python实战项目列表&#xff0c;都有完整且详细的教程&#xff0c;你可以从中选择自己想做…

Day2多种抓包工具介绍以及使用封包监听工具找到挑战数据包实现发送数据包进行挑战

工具相关证书安装指南 Charles https://blog.csdn.net/weixin_45459427/article/details/108393878 Fidder https://blog.csdn.net/weixin_45043349/article/details/120088449 BurpSuite https://blog.csdn.net/qq_36658099/article/details/81487491 Fiddler&#xff1a; 是一…

PyQt5 不规则窗口的显示

PyQt5 不规则窗口的显示QPixmap和QBitmap绘图的效果对比不可以拖动的不规则窗口可以拖动的不规则窗口不规则窗口实现动画效果加载GIF动画效果函数描述setMask(self, QBitmap)setMask(self, QRegion)setMask()的作用是为调用它的控件增加一个遮罩&#xff0c;遮住所选区域以外的…

【Android App】实战项目之仿微信的附近的人(附源码和演示 超详细)

需要全部源码请点赞关注收藏后评论区留言私信~~~ 艺术家常说“距离产生美”&#xff0c;其实距离近才是优势&#xff0c;谁不希望自己的工作事少钱多离家近呢&#xff1f;不光是工作&#xff0c;像租房买房、恋爱交友&#xff0c;大家都希望找个近点的&#xff0c;比如58、赶集…