JVM对象的生命周期(一)

 

文章目录

  • 前言
  • 一、JVM内存结构
  • 二、New对象后在JVM内部会经过哪些流程
    • 1.类加载
    • 2.分配内存
    • 3.对象的初始化
  • 总结

 


前言

JVM包含两个子系统和和两个组件,两个子系统为为类装载(Class Loader)和执行引擎(Execution engine);两个组件为运行时数据区(Runtime data area),本地接口(Native Interface)。
类装载(Class Loader):根据给定的全限定名类名(如:java.lang.Object)来装载class 文件到 运行时数据区(Runtime data area )中的方法区(method area)
执行引擎(Execution engine):执行classes 中的指令。
本地接口(Native Interface) :与native libraries 交互,是其他编程语言交互的接口。
运行时数区域(Runtime data arae):这就是我们常说的JVM 内存

在我们将代码编译成.class文件后,我们的类加载器就会将字节码文件加载到内存(方法区)中,再交给我们的执行引擎区解析成我们CPU可以执行的命令,再交由CPU执行

 

一、JVM内存结构

25a56fa00e89620f85191554152a526f.png

 

二、New对象后在JVM内部会经过哪些流程

1.类加载

new一个对象后,首先看这个类是否已经被类加载器加载过(一般只有当类用到时才加载,懒加载),如果没加载就根据双亲委派模型加载,加载过就下一步
双亲委派机制:
98b6e32affc449438d6c7e3b802f26b9.png

 

2.分配内存

类加载后开始分配内存,分配内存分三种情况,

一、通过逃逸分析去分析你这个对象是否被外部引用,比如一个void方法里面啥也不干,new一个对象,那么这个对象就属于不会被外部引用(废代码),此时,JVM为了减少GC压力会将此对象内存分配在栈中,随着方法的调用完毕,此对象随着栈空间一起被回收。甚至因为jvm内部机制标量替换这个对象都可能不会被New出来

逃逸分析:就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中。
通过开启逃逸分析参数(-XX:+DoEscapeAnalysis)来优化对象内存分配位置,使其通过标量替换优先分配在栈上(栈上分配),
标量替换:通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而是将该对象成员变量分解若干个被这个方法使用的成员变量所代替,这些代替的成员变量在栈帧或寄存器上分配空间,这样就不会因为没有一大块连续空间导致对象内存不够分配
标量与聚合量:标量即不可被进一步分解的量,而JAVA的基本数据类型就是标量(如:int,long等基本数据类型以及reference类型等),标量的对立就是可以被进一步分解的量,而这种量称之为聚合量。而在JAVA中对象就是可以被进一步分解的聚合量。

二、分配在堆中的Eden区,此时需要谈到分配地址的方式
        2.1.指针碰撞:如果分配内存时,eden里面的内存是规整的,就是用过的内存都在一边,没用过的都在另一边,此时分配内存就只需要将指针指示器向空闲的内存移动一段与内存大小相同的距离即可
        2.2.空闲列表:如果eden里面内存不是规整的,那么jvm会维护一个列表记录哪些内存时可用的并且有多大,会从空闲列表里面找出足够容纳对象的内存分配给对象,在更新空闲列表

2.JVM里面分配对象是非常频繁的事情,所以在分配内存时会有并发的问题,即两个线程的对象争抢同一块内存地址,此时JVM解决此问题的方式也有两种
        2.1:对分配内存的操作采用同步处理,采用CAS锁+失败重试机制来保障分配内存的原子性
        2.2:采用TLAB(Thread Local Allocation Buffer),相当于每个线程在堆上已经分配好了一定                   的空间,哪个线程要创建对象分配内存就在哪个线程的TLAB上分配,这样就不存在并                    发的问题了。
如果JVM开启了TLAB,一般在TLAB满了之后才会采用CAS锁+重试的分配机制 

三、大对象直接进入老年代,在jvm中可以配置大对象的大小,当产生的对象内存超过这个值就将直接分配到堆中的老年代里面,默认配置的大对象大小为

 

3.对象的初始化

1.初始化零值:将分配到到的内存空间给对象都赋上零值,比如int类型的初始值就是0;
2.设置对象头:初始化零值之后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头Object Header之中。
3.初始化:执行init方法,一般也就是我们的构造方法为对象赋值

 

上述如有错误欢迎在评论区探讨


总结

这篇文章主要是简单阐述了new 对象后JVM做了哪些事情,可以从一个简单的关键字将java内存模型,类加载,内存分配规则,已经JVM内部各种优化机制等知识点串联起来,当然,这里只是描述了对象的诞生,下篇文章将一起探讨对象是如何死亡的(GC)。如果觉得有帮助,记得点赞收藏

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java对象生命周期可以分为几个阶段。首先,当一个类被加载到JVM时,会在Java生成一个代表这个类的java.lang.Class对象,作为对方法区这些数据的访问入口。接下来,当类被加载、连接和初始化后,它就可以被其它对象或类所调用。当一个对象不再被引用,即不可达时,该对象就会被JVM垃圾回收器所回收掉,从而结束对象生命周期。但是,类在方法区内的数据并不一定会被卸载,除非满足特定条件。 具体来说,当一个类不再被任何对象实例引用,且没有通过反射等手段可访问到该类,同时该类的类加载器已经被垃圾回收,JVM会在方法区垃圾回收的时候对这个类进行卸载。类的卸载过程就是在方法区清空类信息,这样一来,java类的整个生命周期就结束了。需要注意的是,类的卸载是一个比较复杂的过程,不同的JVM实现可能会有不同的具体规则和策略。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java对象生命周期](https://blog.csdn.net/c15158032319/article/details/117262629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值