jvm整体结构以及对象创建与内存分配

堆:存放对象

栈:线程每运行一个方法都会创建一个栈帧 FILO 栈帧内有局部变量表 操作数占 动态链接 方法出口等

本地方法栈: native方法

方法区 :c++结构 类原(代码)信息 静态变量 常量等

计数器:执行到哪一步的计数器

 

堆中分代区:

默认1/3年轻代:eden和survival区,survival区又分为2个区域为s0、s1,默认比例8:1:1

默认2/3老年代

 

-Xss512K 栈

-Xms2048M 堆初始

-Xmx2048M 堆最大,堆会逐渐增大到最大值

-Xmn1024M 堆内年轻代大小

-XX:SurvivorRatio 设置年轻代中Eden区与Survivor区的比值

-XX:MetaspaceSize=256m Metaspace扩容时触发FullGC的初始化阈值,64位默认21MB

-XX:MaxMetaspaceSize=256M 元空间的最大可分配大小,元空间会逐渐增大到最大值

 

 

对象创建流程:

 

1.类加载

2.分配内存

   指针碰撞

   空闲列表

   并发问题

      CAS+失败重试

      本地线程分配缓冲TLAB

3.初始化

4.设置对象头

   对象在内存中存储的布局可以分为3块区域:对象头(Header)、 实例数据(Instance Data) 和对齐填充(Padding)

   对象头(Header)内:

   1.mark word标记字段:存储对象自身的运行时数据, 如哈 希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时 间戳等

   2.klass pointer:堆中的对象类型指针指向方法区的类元信息,虚拟机通过这个指针来确定对象是哪个类的实例

   3.数组长度:只有数组才有

   普通对象(8位补充对齐)

 

   复杂对象

 

     指针压缩:默认开启 比如klasspointer和对象成员变量:­XX:+(-)UseCompressedOops

     开启会压缩占用的内存空间8字节变4字节

5.执行<init>方法

  对象赋值,执行构造方法

 

 

 

内存分配流程:

 

栈内分配条件:

  非对象逃逸,方法内部new的对象,作用域范围不会改变,尝试是否能放在栈帧中,随方法结束自动消失,不用等gc回收。

  对象逃逸:作用域范围发生改变的情况,一个对象在方法中被定义后,可能被外部方法所引用,比如方法内部new的对象 被return出去使用,则称为对象逃逸。

 

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

 

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

 

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

 

 

进堆

 

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

 

大对象

1.超过eden区的最大值

2.可以设置参数来设置成为大对象的值

 

eden和survival s0 s1区默认 8:1:1

先放eden区,如果满了,则清理eden区,存活的对象放入survival的s0,年龄计数器加1

下一次eden区又满了,则清理eden区和s0区,存活的对象放入s1区,年龄计数器加1

下一次eden区又满了,则清理eden区和s1区,存活的对象放入s0区,年龄计数器加1

下一次eden区又满了,则清理eden区和s0区,存活的对象放入s1区,年龄计数器加1

循环

当年龄达到默认(可修改-XX:MaxTenuringThreshold)15时(不同垃圾收集器有所不同)就会放入老年代

 

动态年龄判断

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

 

担保机制

年轻代每次minor gc之前JVM都会计算下老年代剩余可用空间 如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象) 就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了 如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次minor gc后进入老年代的对象的平均大小。 如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full gc,对老年代和年轻代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生"OOM" 当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可用空间,那么也会触发full gc,fullgc完之后如果还是没有空间放minor gc之后的存活对象,则也会发生“OOM”

 

 

GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值