【Java】JVM垃圾回收机制与类加载机制

【Java】JVM垃圾回收机制与类加载机制不同于C++需要编程人员手动释放内存,Java有虚拟机,因此Java不需要程序员主动去释放内存,而是通过虚拟机自身的垃圾回收器(GarbageCollector-GC)来进行对象的回收。Java语言由于有虚拟机的存在,实现了平台无关性,在任意平台都是通过将代码转换为字节码文件,从而在平台下的虚拟机中运行代码的。JVM内存区域分布虚拟机栈:存放每个方法执行时的栈帧,一个方法调用到…

大家好,又见面了,我是你们的朋友全栈君。

不同于C++需要编程人员手动释放内存,Java有虚拟机,因此Java不需要程序员主动去释放内存,而是通过虚拟机自身的垃圾回收器(Garbage Collector-GC)来进行对象的回收。Java语言由于有虚拟机的存在,实现了平台无关性,在任意平台都是通过将代码转换为字节码文件,从而在平台下的虚拟机中运行代码的。

 

JVM内存区域分布

【Java】JVM垃圾回收机制与类加载机制

虚拟机栈:存放每个方法执行时的栈帧,一个方法调用到完成就对应栈帧在虚拟机栈中入栈和出栈的过程。

本地方法栈:和虚拟机栈类似,不过是为Java中native方法服务的。平时所说的“栈内存”指的就是虚拟机栈和本地方法栈的合称。

程序计数器:当前线程执行字节码的行号指示器,字节码解释器工作依赖于它。占用较小的内存空间,不会出现OOM。

堆:即所谓的“堆内存”。JVM所管理最大的一块内存,被所有线程共享。唯一作用就是给对象实例分配内存空间,在分代回收算法中的新生代老年代就在于堆中。

方法区(也称为永久代):不在堆中,被各个线程共享,存储已被JVM加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。其中包括常量池。

另:直接内存,不属于JVM内存区域,与NIO联系紧密,不受JVM内存大小限制。

 

JVM垃圾回收机制

  • 何时进行垃圾回收?

GC本质上是一道守护进程(Daemon Thread),不停的检测堆中是否有不可达对象并释放内存,因此GC在何时发生其实我们是无法预测的。GC通过调用对象的finalize()方法来摧毁对象。

  • 回收谁?

GC回收堆中的不可达对象。

不可达对象的判定:根搜索算法。JVM中有一系列设定的GC Roots,当一个对象到任意一个GC Root都没有引用链时,则说明此对象不可达。

注:JVM并不是通过引用计数法来判断不可达对象的,因为这种办法没法解决循环引用的问题。

 

JVM中的垃圾回收算法

1、标记-清除算法

最基础的算法,GC会判断堆中对象是否不可达,如果满足清理条件(查看该对象是否有必要执行finalize()方法,有无必要的标准是该对象有没有被调用过finalize方法或该对象有没有覆盖finalize()方法,因为finalize()只能被调用一次),则给这个对象进行标记,将对象放在F-queue队列。此时除非对象在finalize()方法中重新获得了引用,否则它就会被清除掉。

以下几种算法不过都是对标记清除算法的改进。

2、复制算法

将内存分为大小相等的两块,当对象不可达后并不是及时清理,而是等待正在使用的内存满了之后,将该内存内还存活的对象整体复制到另一块内存中,复制结束后再清理掉原内存块中的所有内容。这种方法的优点是快速,但牺牲了一半的内存。方法的改进版(事实上也是虚拟机的做法)是只在新生代空间使用复制算法,并且由于新生代对象生命周期往往很短,因此又将新生代区域分为Eden和Survivor空间。其中Eden分配的空间又比Survivor大出很多,从而节省内存空间。如果存活对象过多,使得Survivor区也满,那么就会转移Survivor区对象到老年代。

3、标记-整理算法

标记过程与1一样,将1中的清除过程换成了整理,即将内存中存活的对象归拢到一边,使得内存更“紧凑”一些,整理之后将边界之外的对象清理掉。这种算法是为了防止2算法中出现存活率100%的极端情况,那么复制就没有止境了。

4、分代算法

新生代采用2算法,老年代采用1或3算法。这是由他们的特点决定的,新生代注定了其中很多对象生命周期转瞬即逝,因此复制算法移动的存货对象并不是很多。而老年代存活率较高,只能采用1、3来执行,提高效率。

JVM参数相关

  • 可以调整堆内新生代老年代比例
  • 可以调整对象移入老年代的年龄
  • 可以调整堆内存大小
  • 可以设置每个栈大小
  • 可以设置堆内分区大小
  • 可选择垃圾回收方式

JVM类加载机制

双亲委派模型。

类加载器(ClassLoader)用来实现类的加载动作。JVM中只存在两种不同的类加载器:启动类加载器和其他类加载器。

启动类加载器:即Bootstrap ClassLoader。由C++编写,在JVM内部。其他类加载器都由Java编写,在JVM外部,全部继承于抽象类java.lang.ClassLoader。

 

类加载器之间的层次关系,称为双亲委派模型。

顶层为启动类加载器,下边为扩展类加载器,再下为应用程序类加载器,其中包含多种自定义类加载器。

【Java】JVM垃圾回收机制与类加载机制

 

如果一个类加载器收到了加载类的请求,它首先不会自己去加载,而是委派给它的父加载器去执行。层层委派之后,到了顶层由启动类加载器加载,只有当父加载器反馈无法加载此请求,才会让子加载器去加载。这种结构使得Java类型体系中的加载机制清晰准确,不易造成混乱。

有一种双亲委派模型的异常情况,即类似启动类加载器这种基础的类加载器,本应默认为所有类适用的加载器,但由于一些环境下调用SPI(Service Provider Interface),绕过双亲委派模型的层次结构使得父加载器委派子加载器去完成类加载动作。

还有一种情况,即为了实现模块的动态性、热部署,不再使用双亲委派模型,而是使用更加复杂的网状结构。OSGi技术即是类加载器网状结构的一个最佳实践。

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144945.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CSV文件编辑器——Modern CSV for mac

    CSV文件编辑器——Modern CSV for mac在编辑CSV文档时,大多数人都在寻找一种高度专业的工具来帮助他们做他们想做或实际需要做的任何事情。现代CSV正是这种类型的工具。它提供了大量的选项和功能,同时快速且易于使用。考虑到这一点,当涉及到CSV文档时,这个小程序可以做正确的事情。点击安装》ModernCSVformac快速编辑多单元格编辑复制行、列和单元格。移动行、列和单元格。插入行和列。删除行和列。大文件处理加载数十亿行的文件。只读模式,可实现更高效的文件处理。加载文件的速度比Excel快1

    2022年7月21日
    37
  • smartsvn 用法

    smartsvn 用法都说SMARTSVN是最全的Mac上的SVN客户端工具,分Pro版和基础版,基础版跟Versions差不多,这里找了Pro版下载并激活成功教程:mac版本smartSVN客户端下载:http://www.s

    2022年8月1日
    30
  • 解决:信息中插入avi格式的视频时,提示“unsupported video format”

    解决:信息中插入avi格式的视频时,提示“unsupported video format”

    2022年1月24日
    60
  • JVM成神之路-类加载机制-双亲委派,破坏双亲委派

    概述概念虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接时候用的Java类型。类的生命周期类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备、解析统称为连接上图中,加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须严…

    2022年4月16日
    33
  • 10.17「建议收藏」

    10.17「建议收藏」10.17

    2022年4月20日
    47
  • reaver使用方法

    reaver使用方法闲话少叙使用方法:airmon-ngstartwlan0//启动mon0监控reaver-imon0-bMAC-a-S-vv//普通用法如果,90.9%进程后死机或停机,请记下PIN前四位数,用指令:reaver-imon0-bMAC-a-vv-pXXXX(PIN前四位数)其他命令airodump-ngmon0用来扫描周

    2022年6月4日
    62

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号