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来累加字符串(详见blog另一篇文章JAVA中String与StringBuffer)

  由于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垃圾回收简介相关推荐

  1. Java GC系列(1):Java垃圾回收简介

    转载自  Java GC系列(1):Java垃圾回收简介 这篇教程是系列第一部分.首先会解释基本的术语,比如JDK.JVM.JRE和HotSpotVM.接着会介绍JVM结构和Java 堆内存结构.理解 ...

  2. 细述 Java垃圾回收机制→How Java Garbage Collection Works?

    本文非原创,翻译自How Java Garbage Collection Works? 在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的.和C语言不一样的是Java程序员不需要手动 ...

  3. 理解 Java 垃圾回收机制

    理解java垃圾回收机制有什么好处呢?作为一个软件工程师,满足自己的好奇心将是一个很好的理由,不过更重要的是,理解GC工作机制可以帮助你写出更好的Java应用程序. 这是我个人的主观观点,但我相信一个 ...

  4. Java垃圾回收算法以及垃圾回收器

    文章目录 前言 JVM 内存区域 如何识别垃圾 引用计数法 可达性算法 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中类静态属性引用的对象 方法区中常量引用的对象 本地方法栈中 JNI 引用的对 ...

  5. 假期三天,我肝了万字的Java垃圾回收,看完你还敢说不会?

    大家好,我是狂聊,上一篇已经把 Jvm 的运行区数据和类加载机制聊完了. 今天来说说 Java 垃圾回收,高频面试问题. 提纲附上,话不多说,直接干货 1.什么是垃圾回收? 垃圾回收(Garbage ...

  6. java垃圾回收机制_笔记 | Java垃圾回收机制

    本文经授权转载自程序员杂货铺(ID:speakFramework) 垃圾回收 最近上海的小伙伴是不是要被强垃圾分类搞疯了???哈哈哈哈 上海是个走在前列的城市啊,不光骑自行车闯红灯要被罚钱,垃圾不分类 ...

  7. 细述 Java垃圾回收机制→Types of Java Garbage Collectors

    本文将会介绍各种不同类型的Java垃圾回收器.垃圾回收是Java用来将程序员从分配和释放内存的琐事中解放出来的自动过程. Java有四种类型的垃圾回收器, Serial Garbage Collect ...

  8. 细述 Java垃圾回收机制→Java Garbage Collection Monitoring and Analysis

    本文非原创,翻译自Java Garbage Collection Monitoring and Analysis 在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的.和C语言不一样的 ...

  9. Java垃圾回收工作原理

    在C++中,在heap上分配对象比在stack上分配对象更加昂贵.程序需要找到合适的内存块,再返回内存的地址.但是在Java中垃圾回收器显著地提高了在heap上分配对象的速度.听起来会有些怪,但是这就 ...

最新文章

  1. c++引用与指针的区别
  2. python实现D‘Agostino‘s K-squared test正态分布检验
  3. 用行为级描述方式实现一个加法器电路(基于ISE的设计)(2输入1位全加器电路)
  4. Consul入门02 - 运行Consul代理
  5. Google Gears 体验(2):本机 web 服务器
  6. docker mysql关掉后启动_Docker启动mysql的坑2
  7. nginx log response_nginx优化配置大全
  8. go mysql use 问题,Go语言使用MySql的方法
  9. vue写js代码_vue.js弹出式音乐播放器特效代码
  10. 文本分类器,可自由加载BERT、Bert-wwm、Roberta、ALBert以及ERNIE1.0
  11. Java 数组 定义一个数组,获取数组中的最大值和最小值,奇数个数和偶数个数...
  12. Snagit 12 – 功能强的老牌截图软件
  13. linux酷q运行不了,Linux上使用docker运行酷Q机器人
  14. sqlserver中计算日期差
  15. OpenWRT安装SIM7600CE 4G模块驱动
  16. Funfile免费下载教程,还支持迅雷哦!!!
  17. 苹果开始向全球扩展iAd平台
  18. 机器学习数据预处理----分类型文字数据的处理
  19. JVM JDK JRE JSE的简单介绍
  20. sdjzu 1022

热门文章

  1. 怎样计算系统的可靠性和可用性是几个9?
  2. ubuntu 安装中文输入法(超简靠谱版)
  3. buildroot学习(十)——at91sam9g45软件平台更新
  4. windows开启IIS服务,配置HTTP服务器
  5. 金融量化-金叉和死叉
  6. 什么是 SSH 以及常见 ssh 用法
  7. CAN/CANFD总线基础培训
  8. 什么是JMS(Java Message Service消息服务)
  9. 安全技术与相关安全工具
  10. 土方工程量计算表格excel_土石方计算电子表格