一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载、验证、准备、解析、初始化、使用和卸载七个阶段,其中验证、准备、解析三个部分统称为连接。

加载阶段是整个类加载过程中的一个阶段,在加载阶段,Java虚拟机需要完成以下三件事情:1、通过一个类的全限定名来获取定义此类的二进制字节流。2、将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。3、在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证这些信息被当做代码运行后不会危害虚拟机自身的安全。

所以验证字节码是Java虚拟机保护自身的一项必要措施。

准备阶段是正式为类中定义的变量(静态变量,被static修饰的变量)分配内存并设置类变量初始值的阶段,从概念上讲,这些变量所使用的内存都应当在方法区中进行分配,

解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程。(一开始不理解生命是符号引用,看了这篇博客理解了,https://www.cnblogs.com/shinubi/articles/6116993.html)

初始化阶段

类的初始化做了什么

为类的静态变量赋予正确的初始值、执行类的静态代码块。

按照顺序自上而下运行类中的变量赋值语句和静态语句,如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。

什么时候类会被初始化
只有类或接口被Java程序首次主动使用时才初始化他们。
主动使用(7种)
创建类的实例(new)。
访问某个类或接口的静态变量,或者对该静态变量赋值。
调用类的静态方法。
通过反射方式执行以上三种行为。
初始化子类的时候,会触发父类的初始化。
Java虚拟机启动时被标明为启动类的类。(有main方法的类)
JDK 1.7开始提供的动态语言支持。(了解即可)
除了以上7种情况,其它使用Java类的方式都被看作是对类的被动使用,都不会导致类的初始化。

(初始化参考:https://blog.csdn.net/u013096088/article/details/79439482)

经过半个世纪的发展,今天的内存动态分配与内存回收技术已经相当成熟,一切看起来都进入“自动化”时代,那为什么我们还要去了解垃圾收集和内存分配?答案很简单:当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就必须对这些“自动化”的技术实施必要的监控和调节。

程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。

在堆里面存放着对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(“死去”即不可能再被任何途径使用的对象)了。

判断对象是否存活的算法,引用计数算法,在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

引用计数算法虽然原理简单,但是其必须要配合大量额外处理才能保证正确地工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题。

可达性分析算法

可达性分析算法的基本思路就是通过一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。

垃圾收集

分代收集理论:分代收集建立在两个分代假说之上:1、弱分代假说:绝大多数对象都是朝生夕灭的。2、强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。

这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。

针对不同的区域安排与里面存储对象存亡特征相匹配的垃圾收集算法。

设计者一般至少把Java堆划分为新生代和老年代两个区域。

(针对不同分代的类似名词,新生代收集(Minor GC/Young GC):指目标只是新生代的垃圾收集。老年代收集(Major GC/Old GC):指目标只是老年代的垃圾收集。整堆收集(Full

GC):收集整个Java堆和方法区的垃圾收集。)

标记-清除算法:

最早出现也是最基础的垃圾收集算法是“标记-清除”算法,首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象,标记过程就是对象是否属于垃圾的判定过程。

标记-复制算法

半区复制,但是新生代中的对象有98%熬不过第一轮收集。因此并不需要按照1:1的比例来划分新生代的内存空间。后来进行优化,把新生代分为一块较大的Eden空间和两块较小的Survivor空间,每次分配内存只使用Eden和其中一块Survivor。发生垃圾搜集时,将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上,然后直接清理掉Eden和已用过的那块Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1。(当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要也依赖其他内存区域(实际上大多就是老年代)进行分配担保)。

标记-整理算法

标记-复制算法在对象存活率较高时就要进行较多的复制操作,效率将会降低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。针对老年代对象的存亡特征,提出了标记-整理算法。

经典垃圾收集器

如果说收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者。

新生代垃圾收集器:Serial、ParNew、Parallel Scavenge

老年代垃圾收集器:CMS、Serial Old、Parallel Old

新生代和老年代垃圾收集器:G1

(新生代采用复制算法,暂停所有用户线程;老年代采取标记-整理算法,暂停所有用户线程)

Serial收集器是最基础、历史最悠久的收集器,曾经是HotSpot虚拟机新生代收集器的唯一选择。在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。“Stop The World” 。

ParNew收集器

ParNew收集器实质上是Serial收集器的多线程并行版本,ParNew收集器除了支持多线程并行收集之外,其他与Serial收集器相比并没有太多创新之处,除了Serial收集器外,目前只有它能与CMS收集器配合工作。CMS收集器是HotSpot虚拟机中第一款真正意义上支持并发的垃圾收集器,它首次实现了让垃圾收集线程与用户线程(基本上)同时工作。G1是一个面向全堆的收集器,不再需要其他新生代收集器的配合工作。

Parallel Scavenge收集器

Parallel Scavenge收集器也是一款新生代收集器,它同样是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器。Parallel Scavenge收集器的特点是Parallel Scavenge收集器的目标是达到一个可控制的吞吐量。所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值。

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。从名字(包含“Mark Sweep”)上就可以看出CMS收集器是基于标记-清除算法实现的,它的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为四个步骤,包括:1、初始标记 2、并发标记 3、重新标记 4、并发清除,其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。

初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快;并发标记就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程。重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间比初始标记阶段稍长一些,但也远比并发标记阶段的时间短;最后是并发清除阶段,清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

由于在整个过程中耗时最长的并发标记和并发清除阶段中,垃圾收集器线程都可以与用户线程一起工作,所以从总体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

Garbage First收集器

Garbage First(G1)收集器

(jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

jdk1.9 默认垃圾收集器G1)

G1收集器开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。G1把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获得很好的收集效果。

G1收集器能建立可预测的停顿时间模型,停顿时间模型的意思是能够支持指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间大概率不超过N毫秒这样的目标。

G1收集器之所以能建立可预测的停顿时间模型,是因为它将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个Java堆中进行全区域的垃圾收集。更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间,优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。这种使用Region划分内存空间,以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内获取尽可能高的收集效率。

垃圾收集器在许多场景中都是影响系统停顿时间和吞吐能力的重要因素之一,虚拟机之所以提供多种不同的收集器以及大量的调节参数,就是因为只有根据实际应用需求、实现方式选择最优的收集方式才能获取最好的性能。

3.2 一个对象从创建到回收的整个过程(从类加载到GC),能掌握这个基本就没什么太大的问题;相关推荐

  1. 什么情况下JVM内存中的一个对象会被垃圾回收

    问题1:  哪些对象能回收,哪些对象不能被回收 1.引用计数算法 (ref count) 2.可达性算法  (root searching) JVM 使用可达性算法     判断哪些对象可以被回收.也 ...

  2. java gc 可以对方法区进行回收_浅谈 Java 之 GC

    阅读本文假设你对java内存模型已有一些了解. 1.Java虚拟机中哪些内存需要回收? 先来看看jvm内存模型,如下图 线程隔离的区域随线程而生,随线程而灭:程序计数器可保存着虚拟机字节码指令的地址( ...

  3. 垃圾回收算法与实现系列-学习GC之前的准备工作

    导语   在学习垃圾回收算法之前,首先需要了解什么是Heap.什么是Root.什么是Object.什么是Stack.什么是Pointer,这写概念都是什么,为什么要在垃圾回收算法中使用,使用这些东西有 ...

  4. 精华推荐 | 【JVM深层系列】「GC底层调优系列」一文带你彻底加强夯实底层原理之GC垃圾回收技术的分析指南(GC原理透析)

    前提介绍 很多小伙伴,都跟我反馈,说自己总是对JVM这一块的学习和认识不够扎实也不够成熟,因为JVM的一些特性以及运作机制总是混淆以及不确定,导致面试和工作实战中出现了很多的纰漏和短板,解决广大小伙伴 ...

  5. Activity从创建到显示的整个过程

    写在前面的话 今天有点烦,有点烦.项目写的乱成团,改起需求真要完.此后当个加班狗,无钱无名心要宽. 昨晚写到十一点,我都差点不相信这是我自己了. 今天接着昨天的节奏来,准备写下关于Activity从创 ...

  6. gc机制 php7_PHP7垃圾回收机制详解(附GC处理完整流程图)

    垃圾回收: 简称GC.顾名思义,就是废物重利用的意思. 说垃圾回收机制之前,先接触一下内存泄漏. 内存泄漏: 某大神重口味充满画面感的形象解释: 大概意思就是申请了一块地儿拉了会儿屎,拉完后不收拾,那 ...

  7. PHP7垃圾回收机制详解(附GC处理完整流程图)

    垃圾回收: 简称GC.顾名思义,就是废物重利用的意思. 说垃圾回收机制之前,先接触一下内存泄漏. 内存泄漏: 某大神重口味充满画面感的形象解释: 大概意思就是申请了一块地儿拉了会儿屎,拉完后不收拾,那 ...

  8. 线程创建-结束-回收 教程

    ps aux -L 查看线程信息 且显示进程状态 使用进程的缺点: 进程切换 系统开销较大 开销大的原因 :切换时需要频繁刷新 cache(类似于缓冲区) 和TLB linux不区分线程 进程 线程其 ...

  9. 进程常用指令 (从创建到回收 包含守护)

        进程                           常用命令及基本介绍 ps -ef 查看所有进程信息 (一般需要配合管道使用) ps aux 查看进程信息 且显示进程状态 状态: R ...

最新文章

  1. 效率提升3倍的Paper阅读方法
  2. C++动态数组简单的模拟二元堆
  3. Discuz模板 轻社区Qing_freefresh 完整版
  4. java mysql 二级缓存_深入理解MyBatis中的一级缓存与二级缓存
  5. 论《LEFT JOIN条件放ON和WHERE后的区别》
  6. eclipse 添加jar (servlet api)
  7. 可计算代数数论(2012-12-09 20:56、2013-03-23 21:39、2013-06-23 20:27、2013-06-23 20:32、2014-05-16 17:49)
  8. 微信小程序快递查询插件
  9. 利用Power BI制作分级地图报表
  10. PDF、Word、Excel文件前端预览实操干货都在这!
  11. 博世XC事业部李胤:自动驾驶降温不意外,但这条路肯定会走下去
  12. 在vue中使用echarts,echarts-map:echarts画地图
  13. html 选项按照abcd,怎么把Word里的多个题目的ABCD 选项快速排列整齐
  14. java怎么跳出for循环循环_java如何跳出for循环?
  15. 计算机知识传播策划书,计算机学院硬件知识讲座活动策划书
  16. 瑞芯微和全志的芯片选型和开发异同点
  17. 【报告分享】2020中国异常流量报告-秒针系统中欧商业评论(附下载)
  18. phpstudy安装安全狗找不到服务名
  19. 关于图像处理技术在维护社会安全方面的应用
  20. 计算机网络网上花店毕业论文,网上花店(毕业论文).doc

热门文章

  1. 永不消逝的电波(四):从无线电角度揭秘定位劫持
  2. 基音周期估计-Yin
  3. c语言led左右循环程序,c语言编写程序,将led从左往右,再从右往左依次往返点亮...
  4. 因 N-API 发音对黑人的头发不友好,Node.js 官方将其改名为 Node-API
  5. Alex 我为自己代言
  6. 毫米波雷达ADC数据采集
  7. 大三期末前端页面开发论文
  8. MongoDB启动命令
  9. 苏黎世联邦理工学院计算机硕士申请条件,苏黎世联邦理工学院硕士申请
  10. 学习日记之三:RFC2198文档阅读