您好,登录后才能下订单哦!
这期内容当中小编将会给大家带来有关JVM的分代模型是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
我们将针对jvm堆内存的分代模型做一个详细的解析,和大家一起轻松理解jvm的分代模型。
相信看过其他文章的小伙伴们可能都知道,jvm的分代模型包括:年轻代、老年代、永久代。
那么它们分别代表着什么角色呢?我们先来看一段代码
public class Main { public static void main(String[] args) { while (true){ load(); } } public static void load(){ SysUser sysUser = new SysUser(); sysUser.setAvatar("1"); } }
这段代码本身没有什么特殊的含义,主要是理解jvm的运行机制。
首先一旦执行main()方法,就会把main()方法的栈帧压入main线程的虚拟机栈,然后调用load()方法后,又会把load()方法的栈帧压入虚拟机栈。
接着在执行load()方法时,会在java堆内存中创建一个SysUser对象实例,而栈帧中会有sysUser局部变量引用堆内存中的SysUser对象实例。
如下图:
到这里上篇文章都讲解过,相信大家都能看懂。
变量的存活时间
现在我们思考一下会发现,这个SysUser对象实际上属于一个短暂存活的对象,因为在load()方法执行完毕后,load()方法的栈帧就会出栈。
而一旦出栈,就没有了sysUser这个局部变量来引用SysUser这个对象的实例。
所以,其实这个SysUser对象已经没有用了,但是它还在占用着堆内存的空间,那么对于这种没有引用的对象实例jvm是如何处理的呢?
这就要说到jvm的垃圾回收机制了,jvm本身是有垃圾回收机制的,它是一个后台线程,会把没有人引用的SysUser对象实例给回收掉,不断的释放内存空间。
所以这个SysUser对象实例是一个存活时间很短的对象,可能在执行load()方法的时候被创建出来,执行之后就被垃圾回收掉了。
而这种对象在我们平时的开发中是很常见的,占绝大多数比例。
现在我们将上边的代码改造一下:
public class Main { private static SysUser sysUser = new SysUser(); public static void main(String[] args) { while (true){ load(); } } public static void load(){ sysUser.setAvatar("1"); } }
其实就是把局部变量sysUser变成了静态变量,这样修改后,sysUser不在作为局部变量保存在栈中,而是和class类文件一起保存在方法区中,这样SysUser对象实例就会一直被这个静态变量引用,所以不会被垃圾回收,一直保存在堆内存中。如下图:
分代模型
接下来我们进入核心内容,就是jvm的分代模型了。
上文中我们发现,根据我们的编码方式的不同,采用不同的方式创建和使用对象,对象的存活时间是不同的。
所以jvm将内存区分为两个区域:年轻代和老年代。
年轻代就是我们的第一种局部变量的示例,创建和使用完毕后会被垃圾回收掉。
老年代就是第二种静态变量的示例,创建后需要长期在堆内存中存活。
相信到这里大家就应该理解了什么样的对象是短期存活的对象,什么样的对象是长期存活的对象,那么它们是如何分别存在年轻代和老年代中的呢?为什么要这么区分呢?
其实这与垃圾回收机制是密不可分的。
对于年轻代里的对象,他们的特点是创建后很快就会被回收,而对于老年代里的对象,他们的特点是需要长期存活,所以这两种对象是不能用一种垃圾回收算法进行回收的,所以需要区分成两个。
对于长期存在的静态变量sysUser,其实刚开始的时候也是在年轻代的,那它是什么时候进入老年代的呢?我们下文会讲解这个问题。
那永久代又是什么呢?其实永久代就是我们说的jvm的方法区,用于存放一下类信息的,这部分之后的文章涉及到会详解,现在理解到这就可以了。
新生代的垃圾回收
前文我们了解了,当load方法执行完毕出栈后,里面的局部变量sysUser就没了,堆内存中的SysUser对象就没有引用了,所以会被垃圾回收掉。
那么问题来了,是没有引用后就会立即发生垃圾回收,回收掉没有被引用的对象实例吗?
其实不是这样的,垃圾回收是有触发条件的。
有一个比较常见的场景是这样的,假设我们的代码中创建了大量的对象,导致堆内存中囤积了大量的对象,然后这些对象现在都没有人引用了。
这个时候,如果新生代预先分配的内存空间被占满了,那么我们的代码此时要新创建一个对象的时候,发现新生代空间满了,怎么办?
这个时候就会触发一次新生代的垃圾回收,也称为“Minor GC”或"Young GC",它会尝试把新生代中没有人引用的对象给回收掉,释放空间。
下图表达了这一过程:
长期存活的对象什么时候进入老年代
接下来我们谈论一个话题,静态变量引用的长期存活的对象是什么时候进入老年代的。
上文我们了解到,新生代的对象会经历一次次的垃圾回收,而被静态变量引用的对象因为一直被引用,所以一直不会被回收,所以此时jvm就有了一条规定。
如果新生代中的对象,在经历了15次垃圾回收后,依然坚挺的存活着,那就证明它是个"老年人"了,然后它会被转移到老年代中。
老年代就是存放这些年龄比较大的对象的。
那么老年代中的对象会被垃圾回收吗?
答案是肯定的,因为老年代里的对象随着代码的运行,也是可以不再被任何人引用的,就需要垃圾回收了。
或者说,随着越来越多的对象进入老年代,老年代的内存也会被占满,所以一定是要对老年代进行垃圾回收的。
我们暂时不用考虑具体是怎么回收的,这个内容在之后的文章中我们会有详细的解析。
上述就是小编为大家分享的JVM的分代模型是什么了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。