---恢复内容开始---

  写JAVA程序,一定要了解JVM(JAVA Virtual machine)一些基础知识和垃圾收集。如果对JVM已经很了解了,可以不用继续往下阅读了。本文只针对Java 7, 后续版本的可能跟本文会有所差异。接下来咱们先看一张图:

    

  Java虚拟机分为堆,栈,永久区,程序计数器,虚拟机栈,本地方法栈咱们先从比较重要的地方开始:

  堆: 是所有对象生成存放的地方,它包含新生代和老年代,是所有对象保存的地方。通过制定参数-XX:Xms堆的最小值,-XX:Xmx堆的最大值(图片上写成了Xmn,请见谅)。

  新生代:新生代分为三个区域,Eden区,和两个相同大小的区域Survivor0和Survivor1。生成的地方是Eden伊甸园,万物开始的地方,经过一段时间之后Eden区开始满了,垃圾回收后存活的对象需要向S0或者S1去倒入,咱们可以想象成堆是一个大水缸,当里边的水满出来了,就需要流入到另一个罐子里边去。那么流入罐子的时候要进行的是Minor GC,在这个时候需要STW(Stop the world),Minor GC会耗费很短的STW时间以致于基本程序感知不到。S0和S1是两个相同大小的池子,其中一个池子一直是空的。如果其中的一直池子满了也会进行Minor GC。可以通过设置-XX:Xmn来设置年轻代的大小,可以通过-XX:SurvivorRatio来设置Eden和S0或S1的比例(也就是Eden:Survivor0:Survivor1的比例,默认为8:1:1),比如:新生代为10M,设置-XX:SurvivorRatio=2(2:1)的话, Eden区为5M,S0+S1=5M,每个大小为2.5M。

  老年代:当对象经过多次垃圾回收后仍然存活的话就会移动到老年代。可以通过参数-XX:NewRatio可以设置新生代与老年代的比例,比如-XX:NewRatio=2则新生代的大小占堆空间为1/3,老年代占堆空间的2/3。老年代的GC为Major GC,一般Minor GC发生的时候,网老年代里去倒入数据的时候,发现老年代的空间不足了,所以需要进行GC,那么在这是如果老年代也没有空间了,需要进行Full GC。

  永久区 :  说到永久区包括方法区存储着类的结构信息,字符串池(只限Java 7),运行时常量池(静态方法,运行时常量),Java SE包的信息和方法。如下图所示。

  程序计数寄存器:是当前线程字节码的行号指示器,字节码解释器就是通过更改它然后程序进行分支,循环,跳转以及异常处理。也就是它是线程私有的,当程序正在执行Java方法的时候,那么当前寄存器里边存储的就是执行字节码的行号。如果执行Native方法则计数器的值为Null。

  虚拟机栈:就是程序执行的时候存储的局部变量原始数据类型和引用变量的地址,这个也是线程私有的,每个线程独立的,这块可以通过-Xss来设置其大小。如果进行递归调用时可能

  本地方法栈:与虚拟机栈类似,但是它是在执行一些native方法时存储相应的变量。具体native的方法可能是一些其他语言写的方法,不同的操作系统可能不一样。

下面聊一下垃圾回收:

  串行垃圾回收(-XX:+UserSerialGC):这种方式采用单线程垃圾回收机制,同时使用标记,压缩方法进行垃圾回收,一般用于清除年轻代和老年代的Minor GC和Major GC,这种一般适用于单核CPU的,并且资源消耗比较小的机器上,一般嵌入到工具里。

  并行垃圾回收(-XX:+UseParallelGC):这种方式跟单线程的比,它采用了多线程对年轻代进行垃圾收集(标记-压缩)。可以用过参数-XX:ParallelThreads=n来设置它的线程数,但是对于老年代还是采用单线程的方式进行垃圾收集。这种收集器适用于短时进行很多小的计算,最后进行汇总,然后可以接收长时间的程序停止。比如向一些批处理产生报表,账单,大量数据库查询等。

  并行老年代回收(-XX:+UseParallelOldGC):采用多线程对年轻年轻代进行垃圾回收的同时(年轻代采用复制算法),也用多线程对老年代进行垃圾回收(老年代采用标记-压缩算法)相比并行垃圾回收,应用停止时间会快一些。

  并发标记清除回收(-XX:+UseConcMarkSwapGC) : 并发标记清除(如下图片来自网络,串行标记清除收集器和并发标记清除收集器区别),很适合应用程序低延迟,尤其需要反映很快的应用程序。它的优点是在很短的时间进行STW并且他的STW可以进行定制。多个线程进行标记和清除任务,同时部分用户的线程在某个阶段不会停止,这就是为什么它STW时间很短。采用初始标记(STW,回收线程参考黄色线)ClassLoader能查找到的最近的存活对象进行标记;然后并发的进行标记,被存活对象能找到的对象的引用对象进行再次标记,同时其他用户线程(蓝色部分)也在执行程序;重新标记,STW然后检查那些之前标记的对象进行修正,比如其新添加的对象和它没有引用的对象;最后将并发地去清除这些没有引用的对象。

  它的优点很显然,但是它的缺点也是有的,比如它需要更多的CPU和内存去进行运算,默认情况下,它会启动(CPU个数+3)/3个线程去进行回收,CPU很少的话可能会适得其反。

  多线程在进行清理的时候,同时也会产生其他的垃圾对象没法进行立即回收。

  它更容易产生碎片,因为没有进行压缩,所以大对象处理比较麻烦,比如一个大对象因为老年代没有连续的空间去存放这个大对象,那么就需要更大的内存空间,那么需要至少4G的空间去处理,看到如此多的缺点,需要这么大的空间,新的收集算法产生了,那就是G1,下面继续说G1。  

  

  

  G1收集器-Garbage First Collector(-XX:UseG1GC),这种收集器

---恢复内容结束---

  写JAVA程序,一定要了解JVM(JAVA Virtual machine)一些基础知识和垃圾收集。如果对JVM已经很了解了,可以不用继续往下阅读了。本文只针对Java 7, 后续版本的可能跟本文会有所差异。接下来咱们先看一张图:

    

  Java虚拟机分为堆,栈,永久区,程序计数器,虚拟机栈,本地方法栈咱们先从比较重要的地方开始:

  堆: 是所有对象生成存放的地方,它包含新生代和老年代,是所有对象保存的地方。通过制定参数-XX:Xms堆的最小值,-XX:Xmx堆的最大值(图片上写成了Xmn,请见谅)。

  新生代:新生代分为三个区域,Eden区,和两个相同大小的区域Survivor0和Survivor1。生成的地方是Eden伊甸园,万物开始的地方,经过一段时间之后Eden区开始满了,垃圾回收后存活的对象需要向S0或者S1去倒入,咱们可以想象成堆是一个大水缸,当里边的水满出来了,就需要流入到另一个罐子里边去。那么流入罐子的时候要进行的是Minor GC,在这个时候需要STW(Stop the world),Minor GC会耗费很短的STW时间以致于基本程序感知不到。S0和S1是两个相同大小的池子,其中一个池子一直是空的。如果其中的一直池子满了也会进行Minor GC。可以通过设置-XX:Xmn来设置年轻代的大小,可以通过-XX:SurvivorRatio来设置Eden和S0或S1的比例(也就是Eden:Survivor0:Survivor1的比例,默认为8:1:1),比如:新生代为10M,设置-XX:SurvivorRatio=2(2:1)的话, Eden区为5M,S0+S1=5M,每个大小为2.5M。

  老年代:当对象经过多次垃圾回收后仍然存活的话就会移动到老年代。可以通过参数-XX:NewRatio可以设置新生代与老年代的比例,比如-XX:NewRatio=2则新生代的大小占堆空间为1/3,老年代占堆空间的2/3。老年代的GC为Major GC,一般Minor GC发生的时候,网老年代里去倒入数据的时候,发现老年代的空间不足了,所以需要进行GC,那么在这是如果老年代也没有空间了,需要进行Full GC。

  永久区 :  说到永久区包括方法区存储着类的结构信息,字符串池(只限Java 7),运行时常量池(静态方法,运行时常量),Java SE包的信息和方法。如下图所示。

  程序计数寄存器:是当前线程字节码的行号指示器,字节码解释器就是通过更改它然后程序进行分支,循环,跳转以及异常处理。也就是它是线程私有的,当程序正在执行Java方法的时候,那么当前寄存器里边存储的就是执行字节码的行号。如果执行Native方法则计数器的值为Null。

  虚拟机栈:就是程序执行的时候存储的局部变量原始数据类型和引用变量的地址,这个也是线程私有的,每个线程独立的,这块可以通过-Xss来设置其大小。如果进行递归调用时可能

  本地方法栈:与虚拟机栈类似,但是它是在执行一些native方法时存储相应的变量。具体native的方法可能是一些其他语言写的方法,不同的操作系统可能不一样。

下面聊一下垃圾回收:

  串行垃圾回收(-XX:+UserSerialGC):这种方式采用单线程垃圾回收机制,同时使用标记,压缩方法进行垃圾回收,一般用于清除年轻代和老年代的Minor GC和Major GC,这种一般适用于单核CPU的,并且资源消耗比较小的机器上,一般嵌入到工具里。

  并行垃圾回收(-XX:+UseParallelGC):这种方式跟单线程的比,它采用了多线程对年轻代进行垃圾收集(标记-压缩)。可以用过参数-XX:ParallelThreads=n来设置它的线程数,但是对于老年代还是采用单线程的方式进行垃圾收集。这种收集器适用于短时进行很多小的计算,最后进行汇总,然后可以接收长时间的程序停止。比如向一些批处理产生报表,账单,大量数据库查询等。

  并行老年代回收(-XX:+UseParallelOldGC):采用多线程对年轻年轻代进行垃圾回收的同时(年轻代采用复制算法),也用多线程对老年代进行垃圾回收(老年代采用标记-压缩算法)相比并行垃圾回收,应用停止时间会快一些。

  并发标记清除回收(-XX:+UseConcMarkSwapGC) : 并发标记清除(如下图片来自网络,串行标记清除收集器和并发标记清除收集器区别),很适合应用程序低延迟,尤其需要反映很快的应用程序。它的优点是在很短的时间进行STW并且他的STW可以进行定制。多个线程进行标记和清除任务,同时部分用户的线程在某个阶段不会停止,这就是为什么它STW时间很短。采用初始标记(STW,回收线程参考黄色线)ClassLoader能查找到的最近的存活对象进行标记;然后并发的进行标记,被存活对象能找到的对象的引用对象进行再次标记,同时其他用户线程(蓝色部分)也在执行程序;重新标记,STW然后检查那些之前标记的对象进行修正,比如其新添加的对象和它没有引用的对象;最后将并发地去清除这些没有引用的对象。

  它的优点很显然,但是它的缺点也是有的,比如它需要更多的CPU和内存去进行运算,默认情况下,它会启动(CPU个数+3)/3个线程去进行回收,CPU很少的话可能会适得其反。

  多线程在进行清理的时候,同时也会产生其他的垃圾对象没法进行立即回收。

  它更容易产生碎片,因为没有进行压缩,所以大对象处理比较麻烦,比如一个大对象因为老年代没有连续的空间去存放这个大对象,那么就需要更大的内存空间,那么需要至少4G的空间去处理,看到如此多的缺点,需要这么大的空间,新的收集算法产生了,那就是G1,下面继续说G1。  

  

  

  G1收集器-Garbage First Collector(-XX:UseG1GC),Java 7才推出的。这种收集器将Eden, Survivor, Old Generation分为不同的区域块中。它采用了并发,并行,增量压缩,低延迟,可预测STW时间的收集器。推荐使用的一种垃圾回收算法,相对比较复杂。它和CMS类似,但是它还采用了复制算法和压缩算法。G1是Java 7推荐的算法,一般使用在6G内存中。

  和CMS比较类似,但是也有些区别,CMS不压缩,而它采用压缩。G1并发地标记在整个堆里的存活的对象,当完成标记之后,G1知道哪些区域标记清理之后几乎为空,所以先对哪块区域进行清理,让出大量的空间,这也就是为什么Garbage First了。G1采用了转移,将一部分区域,移动并压缩,放到另一块区域里边,以便腾出更多的空间来使用,并且采用并发地处理,减少停顿时间。

  G1的老年代收集基本流程为初始化标记,STW,然后将年轻代标记存活下来的对象进行标记。并发标记,将那些存活的对象进行标记,此时用户线程是正在执行的。重新标记,对引用对象进行重新标记,并且清除空的区域,腾出新的空间并且计算出可用空间。复制/清除阶段,将那些很少用到的区域进行最先收集,进行老年代和年轻代垃圾清理。此时会产生STW。清理后阶段,将那些很少用到的区域进行压缩和复制,以腾出更多的空间进行内存分配。

  

参考:

  http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

  http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

  http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

Java 7 JVM和垃圾收集的更多相关文章

  1. 深入理解JVM(5)——垃圾收集和内存分配策略

    1.垃圾收集对象 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 哪 ...

  2. 【转载】JVM 学习——垃圾收集器与内存分配策略

    本文主要是对<深入理解java虚拟机 第二版>第三章部分做的总结,文章中大部分内容都来自这章内容,也是博客 JVM 学习的第二部分. 简述 说到垃圾收集(Garbage Collectio ...

  3. JVM、垃圾收集器

    1.Java虚拟机原理 所谓虚拟机,就是一台虚拟的机器.他是一款软件,用来执行一系列虚拟计算指令,大体上虚拟机可以分为系统虚拟机和程序虚拟机, 大名鼎鼎的Vmare就属于系统虚拟机,他完全是对物理计算 ...

  4. JVM中垃圾收集算法总结

      通过前面的介绍我们了解了对象创建和销毁的过程.那么JVM中垃圾收集器具体对对象回收采用的是什么算法呢?本文主要记录下JVM中垃圾收集的几种算法. JVM的垃圾回收的算法 标记-清除算法(Mark- ...

  5. Java之JVM监控工具分享

    Java之JVM监控工具分享 JVM的基本知识常用的也就是类加载机制,内存区域.分配.OOM,GC,JVM参数调优 几个链接自己看: 内存区域&类加载机制 分配策略&垃圾回收算法.收集 ...

  6. 理解JVM之垃圾收集器详解

    前言 垃圾收集器作为内存回收的具体表现,Java虚拟机规范并未对垃圾收集器的实现做规定,因而不同版本的虚拟机有很大区别,因而我们在这里主要讨论基于Sun HotSpot虚拟机1.6版本Update22 ...

  7. 理解JVM之垃圾收集器概述

    前言 很多人将垃圾收集(Garbage Collection)视为Java的伴生产物,实际1960年诞生的Lisp是第一门真正使用内存动态分配与垃圾手机技术的语言.在目前看来,内存的动态分配与内存回收 ...

  8. JVM各垃圾收集器对比

    本随笔是<深入理解Java虚拟机 JVM高级特性与最佳实践>读书笔记. 1.JDK1.7之后的HotSpot虚拟机所包含的所有收集器如下: 解读: 1. 总共有7种垃圾收集器 2.Seri ...

  9. Java基础-JVM调优策略简介

    Java基础-JVM调优策略简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JVM结构分析 1>.JVM结构图 2>.JVM运行时数据区功能说明 JVM管理的内 ...

随机推荐

  1. evak购物车-课程设计(201521123034陈凯欣)

    1.团队课程设计博客链接 https://i.cnblogs.com/EditPosts.aspx?postid=7047127 2.个人负责模块或任务说明 1.Java 编写商品类Goods,商品属 ...

  2. Python可视化----------matplotlib.pylot

    1 >>> import matplotlib.pyplot as plt 2 >>> plt.axis([0,5,0,20]) 3 [0, 5, 0, 20] 4 ...

  3. cas-单点登录-应用说明

    单独在tomcat中启动cas 1,  我的百度网盘中有 cas  和 tomcat-cas 压缩包  http://pan.baidu.com/s/1bnxVRkF   直接解压缩就可以使用. 2, ...

  4. session get和load方法对比

    get测试代码如下: public class Test { public static void main(String[] args) { // TODO Auto-generated metho ...

  5. 二叉树终极教程--BinarySearchTree

    BinarySearchTreeMap 的 实现 public interface Map<K extends Comparable<K>, V> { void put(K k ...

  6. 异常 SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]

    使用Spring 的JDBCtemplate 调用数据库的时候 出现了如下的问题 SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-S ...

  7. [LeetCode] 415 Add Strings && 67 Add Binary && 43 Multiply Strings

    这些题目是高精度加法和高精度乘法相关的,复习了一下就做了,没想到难住自己的是C++里面string的用法. 原题地址: 415 Add Strings:https://leetcode.com/pro ...

  8. MyBatis框架(三)动态SQL,分页,二进制存入数据库图片

    一.动态sql语句,分页 1, <if>条件 <if test="key!=null"> 拼接sql语句 </if> 2, <choose ...

  9. 一张图告诉你移动Web前端所有技术(工程化、预编译、自动化)

    你要的移动web前端都在这里! 大前端方向:移动Web前端.Native客户端.Node.js. 大前端框架:React.Vue.js.Koa 跨终端技术:HTML5.CSS 3.JavaScript ...

  10. 分享一个图片上传插件(TP5.0)

    效果预览图: 该插件主要功能是:可预览裁剪图片和保存原图片,执行裁剪图片后会删除 裁剪的原图片目录,以便减少空间.一.下载附件 地址:https://pan.baidu.com/s/1bpxZhM3 ...