JVM总结+个人整理补充--转

转自 http://blog.csdn.net/Luomingku_1109

JVM是一种规范

Java源文件 --> 编译器 --> 字节码文件

字节码文件 --> JVM(解释器) --> 机器码

Hotspot JVM 后台运行系统线程主要有下面几个

VM Thread,等待JVM到达安全点操作出现

  • stop-the-world 垃圾回收
  • 线程栈dump
  • 线程暂停
  • 线程偏向锁(biased locking) 解除

周期性任务线程

  • 定时器事件(中断),调度周期性操作

GC线程

  • 支持JVM中不同的垃圾回收活动

编译器线程

  • 在运行时将字节码动态编译成本地机器码

信号分发线程

  • 接收发送到JVM的信号并调用适当的JVM方法处理

  • 程序计数器PC(私有),线程执行字节码的行号指示器
  • 虚拟机栈(私有),java方法执行的内存模型,每一个方法会创建一个栈帧,随着方法的调用和执行栈帧会入栈和出栈
  • 本地方法区(私有),为Native方法服务
  • (共享),Runtime的数据,创建的对象和数组都保存在Java堆内存中
  • 方法区/永久代(共享),存储JVM加载的类信息、常量、静态变量,即时编译器编译后的代码
  • 永久代的内存回收针对常量池的回收和类型卸载,收益很小
  • Runtime Constant Pool,运行时常量池,常量池,用来存放编译器生成的字面量和符号引用,类加载后放到方法区运行时常量池

JVM运行时内存

Eden区(伊甸园)

  • Java新对象的出生地(若新对象内存占用大,直接分配到老年代)
  • 当Eden区内存不够时,会触发MinorGC(新生代GC),堆新生代进行垃圾回收

SurvivorFrom

  • 从上次GC中活下来的对象

SurvivorTo

  • 上一次MinorGC在Eden和SurvivorFrom的幸存者

MinorGC的过程采用复制算法(复制->清空->互换)

  • 把Eden和SurvivorFrom区域中存活的对象复制到SurvivorTo区域
  • 如果有对象年龄到达了老年标准(默认15),会送到老年代
  • 所有对象年龄+1(通过一个Age计数器)

清空Eden、survivorFrom

SurvivorFrom和SurvivorTo互换

  • 可以保证对象内存的连续化

老年代

  • 存放应用程序中生命周期长的内存对象
  • 比较稳定,MajorGC不会频繁执行
  • 在执行MajorGC前一般先进行一次MinorGC,使得新生代进入老年代,导致空间不够用触发
  • MajorGC采用标记清除算法
  • 当老年代也满了,会抛出OOM(Out Of Memory)异常

永久代

  • 内存的永久保存区域,存放Class和Meta(元数据)
  • GC不会在主程序运行期永久区域进行清理,导致永久代随着Class的增多而胀满,抛出OOM

JAVA8与元数据

  • 在JAVA8中,永久代被移除,被一个称为"元数据区"的区域所取代
  • 元空间与永久代之间的区别:元空间不在虚拟机中,使用本地内存
  • 类的元数据放入native本地内存,字符串池和类的静态变量放入java堆中

垃圾回收算法

引用计数法

  • 虚拟机并不是通过引用计数算法判断对象是否存活
  • 引用计数法,给对象添加一个引用计数器,有一个地方引用它,计数器+1
  • 当引用失效,计数器-1,任何时刻,计数器为0的对象不可能再被使用

可达性分析算法

  • 为了解决引用计数法的循环引用问题
  • 从称为“GC Roots”的对象作为起始点,从节点开始向下探索,探索所走过的路径称为引用链(Reference Chain)
  • 若在"GC Roots"和一个对象之间没有可达路径,称该对象不可达

标记清除算法(Mark-Sweep)

  • 先标记再清除
  • 效率低,而且会产生大量不连续的碎片,后面分配对象内存可能会无法找到足够大的连续内存

复制算法(Copying)

  • 将内存划分为大小相等的两块,每次只使用其中一块
  • 当一块内存用完,就将存活的对象复制到另一块上,清理已经使用的空间
  • 不用考虑内存碎片的复杂情况,代价是内存缩小为原来的一半
  • 现代商业虚拟机都采用这种收集算法回收新生代

标记整理算法(Mark-Compact)

  • 先标记,然后把对象移动到内存的一端,然后清除端边界外的对象

分代收集算法

  • 大部分JVM采用的方法,核心思想,根据对象存活的声明周期将内存划分为不同域
  • GC划为Tenured/Old Generation 和 Young Generation

新生代与复制算法

  • 大部分JVM的GC对新生代采取Copying算法
  • Minor GC时,将两块空间中还活着的对象复制到另一块Survivor空间

老年代与标记复制算法

  • 永久代存储Class,常量,方法描述
  • 新对象主要在Eden,Survivor的From和To空间
  • 新生代的内存区域发生Minor GC时,存活对象移动到Survivor To空间,清理Eden和Survivor From空间
  • 如果Survivor Space满了,会放到老年代
  • 存活对象躲过一次GC,年龄+1,默认15岁会送到老年代

JAVA四种引用类型

强引用

  • 把一个对象赋给一个应用变量,处于可达状态,不可能被垃圾回收机制回收,Java内存泄漏的主要原因之一

软引用

  • 使用SoftReference类实现,内存足够不会被回收,内存空间不足会被回收,用在对内存敏感的程序中

弱引用

  • WeakReference类实现,比软引用生存期短,只要GC运行,就会回收该对象的内存

虚引用

  • 通过PhantomReference类实现,与引用队列联合使用,跟踪对象被垃圾回收的状态

分区收集算法

  • 分区算法将整个堆空间划分为连续的不同小区间,每个小区间独立使用,可以控制一次回收多少个小区间
  • 每次合理回收若干个小区间(而不是整个堆),从而减少一次GC所产生的停顿

垃圾收集器

Serial(连续)垃圾收集器(单线程、复制算法)

  • 只会使用一个CPU或一条线程去完成垃圾收集工作,并在垃圾收集的同时,暂停其他所有的工作线程
  • 简单高效,对于单个CPU来说,没有线程交互的开销,可以获得单线程的最高垃圾收集效率、
  • java虚拟机运行在Client模式下默认的新生代垃圾收集器

ParNew垃圾收集器(Serial+多线程)

  • Serial收集器的多线程版本
  • ParNew垃圾收集器在垃圾收集过程中同样暂停所有其他工作线程
  • ParNew默认开启和CPU数目相同的线程数,可以通过:-XX:ParallelGCThreads,限制垃圾收集器的线程数
  • Server模式下新生代的默认垃圾收集器

Parallel Scavenge收集器(多线程复制算法、高效)

  • 新生代垃圾收集器,使用复制算法,多线程垃圾收集器
  • 程序达到一个可控制的吞吐量(Throughput)
  • 吞吐量 = 运行时间/(运行时间+垃圾收集时间)
  • 高吞吐量可以高效率利用CPU
  • 自适应调节策略也是ParallelScavenge收集器与ParNew收集器的一个重要区别

Serial Old收集器(单线程标记整理算法)

  • Serial收集器的老年代
  • JDK1.5前与新生代的Parallel Scavenge收集器搭配使用
  • 作为老年代中使用CMS收集器的后备垃圾收集方案

新生代Serial与老年代Serial Old搭配垃圾收集过程

 新生代Parallel Scavenge收集器与ParNew收集器都是多线程的收集器,都使用复制算法,都暂停工作线程

 新生代Parallel Scavenge/ParNew收集器与老年代Serial Old搭配垃圾收集过程图

 

 Parallel Old收集器(多线程标记整理算法)

  • JDK1.6开始提供
  • ParaellScavenge收集器只能搭配老年代的Serial Old收集器,Paralle Old 为老年代同样提供吞吐量优先的垃圾收集器
  • 若系统对吞吐量要求比较高,考虑新生代Parallel Scavenge和年老代Parallel Old收集器的搭配策略

新生代Parallel Scavenge和老年代Parallel Old收集器搭配运行过程

 CMS收集器(多线程标记清除算法)

  • Concurrent mark sweep 收集器是一种老年代垃圾收集器
  • 主要目标是获取最短垃回收停顿时间,和其他老年代使用标记-整理算法不同,使用多线程的标记-清除算法

CMS的工作过程

  • 初始标记,标记一下 GC Roots能直接关联的对象,速度很快,仍然需要暂停所有的工作线程
  • 并发标记,进行GC Roots 跟踪过程,和用户线程一起工作,不需要暂停工作线程
  • 重新标记,用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍需要暂停所有的工作线程
  • 并发清除,清除GC Roots不可达对象,和用户线程一起工作,不需要暂停工作线程,耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户一起并发工作
  • 总体上看,CMS收集器的内存回收和用户线程是一起并发执行的

 G1收集器

Garbage first垃圾收集器是目前垃圾收集器理论发展的前沿成果

  • 基于标记-整理算法,不产生内存碎片
  • 精确控制停顿时间,不牺牲吞吐量前提下,实现低停顿垃圾回收
  • G1收集器避免全区域垃圾收集,把堆内存划分为大小固定的几个独立区域,跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保G1收集器可以在有限时间内获得最高的垃圾收集效率
论读书
睁开眼,书在面前
闭上眼,书在心里
原文地址:https://www.cnblogs.com/YC-L/p/13615530.html