网站首页 > java教程 正文
什么是垃圾回收机制?
回收机制就是 当一些资源被创建使用之后或不在调用的话 就会变成垃圾,垃圾的话会占用空间,这时候就需要释放空间给其他程序使用,所以JAVA拥有自动垃圾回收机制,会在适当的时候自动调用垃圾回收 释放资源,程序员也可以手动调用释放资源等等。
垃圾回收机制的意义
Java语言中一个显著的特点就是引入了垃圾回收机制,使得Java程序员最头疼的内存管理的问题迎刃而解,在编写程序的时候不需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。
ps:内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为“对象游离”。
1.垃圾收集算法的核心思想
Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。
垃圾收集算法的核心思想是:对虚拟机可用内存空间的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,因此需要开发人员做比较深入的了解。
2.触发主GC(Garbage Collector)的条件
JVM进行次GC的频率很高,但因为这种GC占用时间极短,所以对系统产生的影响不大。更值得关注的是主GC的触发条件,因为它对系统影响很明显。总的来说,有两个条件会触发主GC:
(1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用。因为GC在优先级最低的线程中进行,所以当应用忙时,GC线程就不会被调用,但以下条件除外。
(2)Java堆内存不足时,GC会被调用。当应用线程在运行,并在运行过程中创建新对象,若这时内存空间不足,JVM就会强制地调用GC线程,以便回收内存用于新的分配。若GC一次之后仍不能满足内存分配的要求,JVM会再进行两次GC作进一步的尝试,若仍无法满足要求,则 JVM将报“out of memory”的错误,Java应用将停止。
由于是否进行主GC由JVM根据系统环境决定,而系统环境在不断的变化当中,所以主GC的运行具有不确定性,无法预计它何时必然出现,但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的。
3.减少GC开销的措施
根据上述GC的机制,程序的运行会直接影响系统环境的变化,从而影响GC的触发。若不针对GC的特点进行设计和编码,就会出现内存驻留等一系列负面影响。为了避免这些影响,基本的原则就是尽可能地减少垃圾和减少GC过程中的开销。具体措施包括以下几个方面:
(1)不要显式调用System.gc()
此函数建议JVM进行主GC,虽然只是建议而非一定,但很多情况下它会触发主GC,从而增加主GC的频率,也即增加了间歇性停顿的次数。这里特别需要说明的是,在代码中显示的调用System.gc(),并不一定能够进行GC,这个我们可以通过finalize()方法进行验证,即主动调用System.gc(),并不一定每次都调用finalize()方法。finalize()方法的特征是在对象被回收之前, 首先调用finalize()方法。
(2)尽量减少临时对象的使用
临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,从而延长了出现上述第二个触发条件出现的时间,减少了主GC的机会。
(3)对象不用时最好显式置为Null
一般而言,为Null的对象都会被作为垃圾处理,所以将不用的对象显式地设为Null,有利于GC收集器判定垃圾,从而提高了GC的效率。
(4)尽量使用StringBuffer,而不用String来累加字符串
由于String是固定长的字符串对象,累加String对象时,并非在一个String对象中扩增,而是重新创建新的String对象,如 Str5=Str1+Str2+Str3+Str4,这条语句执行过程中会产生多个垃圾对象,因为对次作“+”操作时都必须创建新的String对象,但这些过渡对象对系统来说是没有实际意义的,只会增加更多的垃圾。避免这种情况可以改用StringBuffer来累加字符串,因StringBuffer 是可变长的,它在原有基础上进行扩增,不会产生中间对象。
(5)能用基本类型如Int,Long,就不用Integer,Long对象
基本类型变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好使用基本变量。什么情况下需要使用Integer?
(6)尽量少用静态对象变量
静态变量属于全局变量,不会被GC回收,它们会一直占用内存。
(7)分散对象创建或删除的时间
集中在短时间内大量创建新对象,特别是大对象,会导致突然需要大量内存,JVM在面临这种情况时,只能进行主GC,以回收内存或整合内存碎片, 从而增加主GC的频率。集中删除对象,道理也是一样的。它使得突然出现了大量的垃圾对象,空闲空间必然减少,从而大大增加了下一次创建新对象时强制主GC 的机会。
4.垃圾回收算法
(1)引用计数收集器
引用计数是垃圾收集的早期策略。在这种方法中,堆中每一个对象都有一个引用计数。当一个对象被创建了,并且指向该对象的引用被分配给一个变量,这个对象的引用计数被设置为1。比如新建一个对象A a=new A();然后a被分配给另外一个变量b,也就是b=a;那么对象a的引用计数+1。当任何其他变量被赋值为对这个对象的引用时,计数加1。当一个对象的引用超过生存期或者被设置一个新的值时,对象的引用计数减1,比如令b=c,则a的引用计数-1。任何引用计数为0的对象可以被当做垃圾收集。当一个对象被垃圾收集的时候,它引用的任何对象计数减1。在这种方法中,一个对象被垃圾收集后可能导致后续其他对象的垃圾收集行动。比如A a=new A();b=a;当b被垃圾回收以后,a的引用计数变为0,这样导致a也被垃圾回收。
方法的好处:引用计数收集器可以很快执行,交织在程序的运行之中。这个提醒对于程序不能被长时间打断的实时环境很有利。
方法的坏处:引用计数无法检测出循环(即两个或者更多的对象互相引用)。循环的例子如,父对象有一个子对象的引用,子对象又反过来引用父对象。这样对象用户都不可能计数为0,就算它们已经无法被执行程序的根对象触及。还有一个坏处就是,每次引用计数的增加或者减少都带来额外的开销。
(2)追踪收集器
垃圾检测通常通过建立一个根对象的集合并且检查从这些根对象开始的可触及性来实现。如果正在执行的程序可以访问到的根对象和某个对象之间存在引用路径,这个对象就是可触及的。对于程序来说,根对象总是可以访问的。从这些根对象开始,任何可以被触及的对象都是被认为是“活动”的对象。无法被触及的对象被认为是垃圾,因为它们不在影响程序的未来执行。
跟踪收集器是追踪从根结点开始的对象引用图。在追踪过程中遇到的对象以某手方式打上标记。总的来说,要么在对象本身上设置标记,要么用一个独立的位图来设置标记。当追踪结束时,未被标记的对象就是无法触及的,从而可以被收集。
基本的追踪算法被称作“标记并清除”。这个名字指出垃圾手机的两个阶段。在标记阶段,垃圾收集器遍历引用树,标记每一个遇到的对象。在清除阶段,未被标记的对象被释放,释放对象后获得的内存被返回到正在执行的程序。在Java虚拟机中,清除步骤必须包括对象的终结。
最后,开发这么多年我也总结了一套学习Java的资料与面试题,私信我发给你,另外如果你在技术上面想提升自己的话,可以关注我后面更新的内容,有时间记得帮我点下转发让更多的人看到哦。
- 上一篇: Java的垃圾回收机制-GC算法和种类
- 下一篇: 解析Java、Python与Go的垃圾回收机制
猜你喜欢
- 2024-11-08 咱们从头到尾说一次 Java 的垃圾回收
- 2024-11-08 了解Java垃圾收集(java中垃圾收集)
- 2024-11-08 Java 垃圾回收(java垃圾回收)
- 2024-11-08 Java JVM垃圾回收算法浅记(java 垃圾回收机制)
- 2024-11-08 Java 经典垃圾回收器详解(java 垃圾回收器有哪些)
- 2024-11-08 JVM系列(十):JVM 垃圾回收机制详解分析
- 2024-11-08 看连环画,Java垃圾回收机制,简单易懂
- 2024-11-08 【虚拟机】深入理解java虚拟机【垃圾回收算法】
- 2024-11-08 Java面试必背——垃圾回收机制及如何手动触发垃...
- 2024-11-08 Java垃圾回收算法(java垃圾回收算法cms执行的顺序是)
你 发表评论:
欢迎- 最近发表
-
- pyinstaller打包python程序高级技巧
- 将python打包成exe的方式(python打包成exe的方法)
- Python打包:如何将 Flask 项目打包成exe程序
- py2exe实现python文件打包为.exe可执行程序(上篇)
- 如何将 Python 项目打包成 exe,另带卸载功能!
- Python打包成 exe,太大了该怎么解决?
- 可视化 Python 打包 exe,这个神器绝了!
- 案例详解pyinstaller将python程序打包为可执行文件exe
- Cocos 3.x 菜鸟一起玩:打包window程序
- 怎么把 Python + Flet 开发的程序,打包为 exe ?这个方法很简单!
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)