jvm:6jvm分代模型:年轻代老年代永久代

鮀城小帅 鮀城小帅     2022-12-30     248

关键词:

1. 背景引入

JVM内存的分代模型: 年轻代、老年代、永久代

我们在代码里创建的对象,都会进入到 Java 堆内存中,方法的栈帧都会压入到Java虚拟机栈里,而方法如果有局部变量,该局部变量就会在方法所对应栈帧里去引用Java对列出里的对象实例。

最终,就会执行该对象的方法。比如上图的 ReplicaManager对象的 load() 方法。

2. 大部分对象都是存活周期极短的

上述的代码中, ReplicaManager 对象,是属于短暂存活的一个对象。当最终执行到 replicaManager.load() 方法完毕, loadReplicasFromDisk()方法就会结束。

一旦方法结束,那么 loadReplicasFromDisk()方法的栈帧就会出栈。

此时一旦没人引用这个 ReplicaManager 对象,就会被 JVM 的垃圾回收线程给回收掉,释放内存空间。

然后在 main() 方法的 while 循环里,下一次循环再次执行 loadReplicasFromDisk()方法的时候,又会走一遍上面的程序,重新将方法入栈,将实例对象放在Java堆里,将栈帧的局部变量指向Java堆内存的实例。

最后在load() 方法执行完毕后,loadReplicasFromDisk()方法结束,又再次被JVM垃圾回收线程回收掉。

从这段代码和分析,可以得知,大部分在我们代码里创建的对象,其实都是存活周期很短的。这种对象,在我们写的 Java 代码中,占到绝大部分的比例。

3. 少数对象是长期存活的

上述代码中,给 Kafka 类定义了一个静态变量,也就是 “replicaManager” ,这个 Kafka 类是在 JVM 的方法区里的。

然后让  “replicaManager” 引用了一个在 Java 堆内存里创建的 ReplicaManager 实例对象,如下图

接着在 main() 方法中,就会在 while 循环里不停的调用 ReplicaManager 对象的 load() 方法,做成一个周期性运行的模式。

这个时候,这个 ReplicaManager 实例对象,是会一直被 Kafka 的静态变量引用的,然后会一直驻留在 Java 堆内存里,是不会被垃圾回收掉的。

因为该实例对象需要长期被使用,周期性的被调用 load()  方法,所以它就成为了一个长时间存在的对象,轻易不会被垃圾回收

4. JVM 分代模型: 年轻代和老年代

已知,根据写代码方式的不同,采用不同的方式来创建和使用对象,其实对象的生存周期是不同的。

所以 JVM 将 Java堆内存划分为了两个区域,一个是年轻代,一个是老年代

年轻代,就是把第一种代码示例中,创建和使用完之后立马就要回收的对象放在里面。

老年代,就是把第二种代码示例中,创建之后需要一直长期存在的对象放在里面。

 

如下示例代码:

 在上述代码中, Kafka 的静态变量“fetcher” 引用了 ReplicaFetcher 对象,是长期需要驻留在内存里面使用的。

该对象会在年轻代停留一会儿,最终会进入老年代。

进入 main() 方法之后,会先调用loadReplicasFromDisk() 方法,业务含义是系统启动就从磁盘加载一次副本数据,这个方法的栈帧会入栈。

然后在这个方法里面创建 ReplicaManager 对象,这个对象用完就会回收,所以是放在年轻代里的,由栈帧里的局部变量来引用。

如下图:

然后一旦 loadReplicasFromDisk() 方法执行完毕,方法的栈帧就会出栈,对应的年轻代里的 ReplicaManager对象也会被回收掉。如下图:

接着会执行一段 while循环代码,他会周期性的调用 ReplicaFetcher 的 fetch() 方法,去从远程加载副本数据。

所以 ReplicaFetcher 这个对象以为被 Kafka 类的静态变量 fetcher 给引用了,所以它会长期存在于老年代里,持续被使用。

5. 为什么要分成年轻代和老年代?

主要和垃圾回收有关,对于年轻代里的对象,他们的特点是创建之后很快就会被回收,所以需要一种垃圾回收算法;对于老年代里的对象,他们的特点是需要长期存在,所以需要另外一种垃圾回收算法,所以需要分成两个区域来放不同的对象

6. 什么是永久代

JVM 里的永久代就是 前面的方法区。永久代里就是放一些类信息的。

 7. 思考题

方法区会不会进行垃圾回收?

答:以下几种情况,方法区会进行垃圾回收。

  • 首先该类的所有实例对象都已经从 Java 堆内存里被回收
  • 其次加载这个类的 ClassLoader 已经被回收
  • 最后,对该类的 Class 对象没有任何引用

满足上面三个条件就可以回收该类了。

jvm中的年轻代老年代持久代gc

1.分代的意义:其实不分代完全可以,分代的唯一理由就是优化GC性能。如果没有分代,所有的对象都在一块,GC的时候要找到哪些对象没用,就会对堆的所有区域进行扫描。而很多对象都是朝生夕死的,如果分代的话,可以把新... 查看详情

jvm系统优化实践:分代模型

您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~大部分在代码里创建的对象,存活周期都是极短的,只有少数对象是长期存活的,如静态类和静态变量。采用不同方式创建和使用对象,其生存周期也不同。因此,J... 查看详情

gc年轻代老年代持久代

...yaoyuan23/p/5587548.html  虚拟机中的共划分为三个代:年轻代(YoungGeneration)、老年代(OldGeneration)和持久代(PermanentGeneration)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年... 查看详情

jvm年轻代老年代持久代gc

虚拟机中的共划分为三个代:年轻代(YoungGeneration)、老年代(OldGeneration)和持久代(PermanentGeneration)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影... 查看详情

jvm中的年轻代老年代持久代gc

 虚拟机中的共划分为三个代:年轻代(YoungGeneration)、老年代(OldGeneration)和持久代(PermanentGeneration)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收... 查看详情

jvm之年轻代(新生代)老年代永久代以及gc原理详解gc优化

关于JVM,也许你听过这些术语:年轻代(新生代)、老年代、永久代、minorgc(younggc)、majorgc、fullgc不要急,先上图,这是jvm堆内存结构图  仔细的你发现了图中有些分数8/10和1/10,这是默认配置下各个代内存分配比例。举... 查看详情

深入理解jvm-分代的基本概念(代码片段)

前言​本次讲述jvm分代模型的基础概念,这个专栏会由浅入深的不断构建起来,循序渐进,是非常基础的内容概述:讲述JVM的基础分代模型以及版本升级的处理。对象分配的基础概念和知识。长期存活的对象是如... 查看详情

jvm之堆内存

堆结构分代图堆结构分代的意义  Java虚拟机根据对象存活的周期不同,把堆内存划分为几块,一般分为新生代、老年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略。  堆内存是虚拟机管理的内存中最大的一... 查看详情

每日一面-java中,描述一下什么情况下,对象会从年轻代进入老年代?(代码片段)

...estion/437632685,解答为个人原创KeyTakeawayJava默认启用了分代GC启用分代GC的,在发生YoungGC,更准确地说是在Survivor区复制的时候,存活的对象的分代年龄会加1。当分代年龄=-XX:MaxTenuringThreshold指定的大小时,对... 查看详情

jvmgc

...用的GC回收期有Serial/Parallel/CMS/G1,我们目前JVM内存一般是分代回收,各个代根据功能采用了不同的GC回收器,直接使用一张非常直观的网上图片 GC类型不同的代分为不同的GC类型,一般我们把年轻代叫youngGC,老年代叫oldGC;有... 查看详情

堆中的新生代与老年代

1.为什么会有年轻代我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪... 查看详情

jvm之堆内存(年经代,老年代)(代码片段)

...、为什么会有年轻代  我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要... 查看详情

jvm垃圾回收算法

1.堆的分代和区域(年轻代)YoungGeneration(eden、s0、s1 space)  MinorGC(老年代)OldGeneration(Tenuredspace)   MajorGC||FullGC(永久代)PermanentGeneration(Permanent space)【方法区(methodarea)】& 查看详情

jvm年轻代

1.为什么会有年轻代我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪... 查看详情

jvm垃圾回收算法及分代垃圾收集器

一、垃圾收集器的分类1、次收集器    ScavengeGC,指发生在新生代的GC,因为新生代的Java对象大多都是朝生夕死,所以ScavengeGC非常频繁,一般回收速度也比较快。当Eden空间不足以为对象分配内存时,会触发ScavengeGC。   ... 查看详情

jvm系列之.jvm内存模型如何正确运用操作?本文详解

...区域:堆区:堆区是JVM中最大的一块内存区域,按照垃圾分代收集的角度划分,又可以分成年轻代和老年代,而年轻代内存又被分成三部分,Eden空间、FromSurvivor空间、ToSurvivor空间,默认情况下年轻代按照8:1:1的比例来分配;方... 查看详情

jvm内存设置

...是FullGC后永久区的1.2到1.5倍1.2xto1.5xpermanentgenerationspace】年轻代Xmn的设置为老年代存活对象的1-1.5倍。老年代的内存大小设置为老年代存活对象的2-3倍。BTW:1、Sun官方建议年轻代的大小为整个堆的3/8左右,所以按照上述设置的方... 查看详情

java虚拟机:jvm内存分代策略

...年代和永久代(对HotSpot虚拟机而言),这就是JVM的内存分代策略。    为什么要分代?    堆内存是虚拟机管理的内存中最大的一块,也是垃圾回收最频繁的一块区域,我们程序所有的对象实例都存... 查看详情