本文是《深入理解Java虚拟机 JVM高级特性与最佳实践》的读书笔记


在介绍Java的垃圾回收方法之前,我们先来了解一下Java虚拟机在执行Java程序的过程中把它管理的内存划分为若干个不同的的数据区的什么?

1.Java运行时数据区的划分

如下图:

其中程序计数器,虚拟机栈,本地方法栈这3个区域的内存随线程而生,随线程而灭的,因此这几个区域的内存分配与回收都是有确定的,我们不需要考虑这几个区域的内存的分配与回收。而堆和方法区则不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分的内存的分配和回收都是动态的,垃圾收集器关注的就是这部分内存(堆和方法区)。

下面我们先简单介绍一下这几部分区域存放的什么东西;

  1. 程序计数器:(线程私有)当前线程所执行的字节码的行号指示器,解释器工作时就是通过改变这个计数器的值来取得下一条需要执行的指令。
  2. Java虚拟机栈:(线程私有)描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从刻调用直到执行完成,就对应于栈帧在虚拟机栈中的入栈和出栈的过程。我们常说的栈内存就是这个。
  3. 本地方法栈:(线程私有)与Java虚拟机栈类似,只不过这是为虚拟机会用到的Native方法服务的,它也会抛出StackOverflowError和OutOfMemoryError异常。
  4. Java堆:(所有线程共享)几乎所有的对象实例都会在这里分配内存,Java堆还可以细分为新生代和老年代;
  5. 方法区:(线程共享)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;(在某些虚拟机上也称为永久代)。

2 Java(JVM)的垃圾回收机制

2.1 哪些内存需要回收?

在Java中,都是通过可达性分析来对象是否存活的(如果对象是死的,那么它所占用的内存就是需要回收的)。可达性分析算法的基本思想就是通过一系列被称为“GC Roots”的对象开始,从这些节点向下搜索,搜索走过的路线称为引用链。当一个对象没有在任何引用链上出现,则这个对象会被判定为不可用的(死的,可回收的)。

在被可达性分析算法判定为不可用的对象,也并非是一定就是会被回收的,它们还会经历一次筛选的过程,筛选的条件就是此对象是不是要执行finalize()方法,如果对象没有覆盖finalize()方法或它的finalize()方法在上一次垃圾回收器工作时已经执行过了,则被判定为不用执行finalize()方法(对象会在这次回收中被回收),若判定为需要执行finalize()方法,则这个对象会被放置在一个F-Queue队列中,稍后虚拟机会建立一个finalizer线程(低优先级)来触发这个方法,但虚拟机不承诺会等它执行完这个方法。(也就是这个对象可能在执行finalize()方法时被回收了),如果在finalize()方法中,对象加入了任何一个引用链中,则这个对象在这次回收器工作时就不会被回收了。

在Java中,有几种可作为GC Roots对象:虚拟机栈(栈帧中的本地变量表)中引用对象。方法区中类静态属性和常量引用的对象和本地方法栈中JNI引用的对象;

2.2 垃圾回收算法

2.2.1 标记-清除(Mark-Sweep)算法

首先会利用前面的可达性分析算法标记出需要回收的对象,在标记完成后就统一回收所有被标记的对象,这个算法的缺点主要有:

  • 效率问题,在标记和清除两个过程中效率都不高;
  • 空间问题,标记清除之后会产生大量的内存碎片,碎片太多,可能导致在下次为大对象分配内存时,提前触发一次垃圾回收动作;

2.2.2 复制算法(Coping)

将可用的内存分为两块,每次只使用其中的一块,这样每次只需要顺序分配内存就可以,当一块的内存用完后,就把还存活的对象复制到另一块内存中去,然后对使用过的内存空间进行回收就可以了。(一般不会采用平均分成两块的方式,现代虚拟机一般会将内存分成一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和一块Survivor空间,回收时,将Eden空间和Survivors空间里还存活的对象复制到另一块没有使用的Survivor空间中,然后清理掉用过的空间),一般会这种算法回收新生代的内存空间;

2.2.3 标记-整理(Mark-Compact)算法

先利用可达性分析算法标记需要回收的对象,然后就让还存活的对象(出现在任何引用链中的对象)都向一端移动,然后清理掉端边界外的内存。(一般用来回收老年代的对象);

3 什么时候回收

大多数情况下,对象优先在Eden区中分配(大对象直接在老年代分配),当Eden没有足够空间时,JVM就会发起一次Minor GC。在进行Minor GC 之前,JVM会检查老年代最大可用的空间是否大于新生代所有对象的空间,如果成立,则Minor GC是安全的,否则,JVM就会去检查HandlePromotionFailure设置值是否允许担保失败。如果允许担保失败,则会继续检查老年代最大可用空间是否大于历次晋升到老年代对象的平均大小,如果是,则会尝试进行Minor GC(若失败,就会进行一次Full GC);否则就会改为进行一次Full GC;

Java的垃圾回收和内存分配策略的更多相关文章

  1. 【java虚拟机序列】java中的垃圾回收与内存分配策略

    在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...

  2. Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法

    在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...

  3. java 垃圾回收及内存分配策略

    一.在垃圾收集器对堆进行回收前,首先需要判断对象是否"存活",对已经"死去"的对象进行回收 判断对象是否存活:引用计数法和可达性分析法 引用计数法:给对象添加一 ...

  4. Java GC 垃圾回收算法 内存分配

    垃圾回收(Garbage Collection, GC)是Java不同于c与c++的重要特性之一. 他帮助Java自动清空堆中不再使用的对象. 由于不需要手动释放内存,程序员在编程中也可以减少犯错的机 ...

  5. [jvm]垃圾回收与内存分配策略

    一.垃圾回收算法 概述 JVM中,当创建的对象不再被使用的时候,此时我们认为他是无用的“垃圾”:在现代主流的商用jvm中,都是通过可达性分析来判断对象是否存活的.这个算法的基本思想是通过一系列“GCR ...

  6. Java虚拟机----垃圾回收与内存分配

    一.垃圾回收的对象: 在Java的运行时数据区中,程序计数器和虚拟机栈.本地方法栈是随着线程的生灭而生灭,栈当中栈帧的大小在编译的时候已知,在方法结束之后栈帧出栈,这部分的垃圾回收是明确的,因此需要讨 ...

  7. Java虚拟机垃圾收集器与内存分配策略

    Java虚拟机垃圾收集器与内存分配策略 概述 那些内存须要回收,什么时候回收.怎样回收是GC须要完毕的3件事情. 程序计数器.虚拟机栈与本地方法栈这三个区域都是线程私有的,内存的分配与回收都具有确定性 ...

  8. JVM学习02:GC垃圾回收和内存分配

    JVM学习02:GC垃圾回收和内存分配 写在前面:本系列分享主要参考资料是  周志明老师的<深入理解Java虚拟机>第二版. GC垃圾回收和内存分配知识要点Xmind梳理 案例分析1-(G ...

  9. NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配

    在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...

随机推荐

  1. jsp基础

    1.1动态页面 动态页面的优势: 1.交互性:网页会根据用户的要求和选而动态改变和显示内容; 2.自动更新:无需改变页面代码,便会自动更新的页面内容; 3.随机性:当不同的时间,不同的人访问同一网址时 ...

  2. 百度广告 高亮 Chrome插件(附源码)

    一前言 百度最近是上了舆论头条了,相信中过百度毒的人对百度都反感.百度自己挖了这么多坑,终究还是要自己来填.国内网民使且最频繁的搜过 还是以百度为主,而百度依靠这种市场占有率靠他的广告竞价排名大发横财 ...

  3. PPS传奇生死

    地址 :http://game.pps.tv/events/cqss_sign 调用encryptedString('password') RSA加密,通过function(a) 定义 window= ...

  4. 修改hosts文件在本地使域名解析到指定IP

    # Additionally, comments (such as these) may be inserted on individual  # lines or following the mac ...

  5. 一个python的邮件发送脚本,自动,定时,可以附件发送,抄送,附有说明文件

    #!/bin/env python # -*- coding: utf-8 -*- import datetime import smtplib import os,sys from email.mi ...

  6. ftp文件的部署

    之前在公司搭建了一个静态资源服务器,现在来记录一下 我们是通过搭建vsftp服务,然后结合apache.访问方式为http的方式 一:VSFTPD环境安装 首先我们就是要查看一下vsftpd是否有安装 ...

  7. UICollectionView中使用 UICollectionViewFlowLayout进行布局(模仿苹果相册)

    现在都知道,在初始化UICollectionView的时候,必须要传入一Layout对象,进行布局管理.这也是collectionview和tableview的明显区别,通过collectionvie ...

  8. Javascript提交表单

    <form action="login.do?act=login" method="post"> <input type="subm ...

  9. theano broadcasting

    当我们使用函数对两个数组进行计算时,函数会对这两个数组的对应元素进行计算,因此它要求这两个数组有相同的大小(shape相同).如果两个数组的shape不同的话,会进行如下的广播(broadcastin ...

  10. 【Beta】Scrum07

    Info 由于编译考试,会议记录推迟发布.18~19两天工作暂停:同时由于有组员外出不在学校,本次会议采用线上会议形式 时间:2016.12.17 21:35 时长:15min 地点:讨论组 类型:线 ...