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

  写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. list,set,map总结

    学习了集合,脑子里list,set,map之间的关系有混乱,在这里整理一下.有兴趣的朋友可以看下. 先看下 list,set,map各自的特点

  2. Java程序设计——学生基本信息管理系统

    1.团队课程设计博客链接 http://www.cnblogs.com/handsome321/p/7067121.html 2.个人负责模块说明 本组课题:学生信息管理系统 本人任务:插入.删除学生 ...

  3. 201521123066《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  4. SVN不出现绿色对勾的情况

    就目前而言,我出现了两种情况. Num1:电脑云盘可能不兼容,导致无法出现svn提示小icon:----->删除云盘重新启动. Num2:被设置覆盖.----->鼠标右键-->Tor ...

  5. Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)

    有公网环境的服务器可以直接看 Hyperledger Fabric 1.0 从零开始(二)--环境构建(公网) ,本篇内容与上篇相似,只不过环境搭建需要在内网下,也就是网络被限制的情况下. 1:环境构 ...

  6. D3--数据可视化实战总结

    d3理解 标签(空格分隔): 未分类 1.绑定数据 [x] 定义:通过循环的方式将数据绑定在dom元素上,每个数据对应一个元素,所以这个数据的值就能来设定dom元素的width,height,x,y坐 ...

  7. IDEA导入Eclipse项目 【未结束的注释、非法类型的开始、缺少符号】

    如果我们导入Eclipse项目的使用出现了未结束的注释.非法类型的开始.缺少符号这么一些编译时期的错误,而我们的代码明明看起来就是正常的-. 我们去检查一下是否编码的问题:把FileEncoding全 ...

  8. 编程从入门到提高,然后放弃再跑路(Java)

    1.Java入门篇 1.1 基础入门和面向对象 1.1.1 编程基础 [01] Java语言的基本认识 [02] 类和对象 [03] 类的结构和创建对象 [04] 包和访问权限修饰符 [05] 利用p ...

  9. SSH框架搭建最终版【测试、log4j、baseDao】

    最详细搭建SSH框架环境 本博文主要是讲解如何搭建一个比较规范的SSH开发环境,以及对它测试[在前面的搭建中,只是整合了SSH框架,能够使用SSH实现功能],而这次是相对规范的. 导入开发包 在Str ...

  10. Hibernate第五篇【inverse、cascade属性详解】

    前言 上一篇博文已经讲解了一对多和多对一之间的关系了,一对多和多对一存在着关联关系(外键与主键的关系).本博文主要讲解Inverse属性.cascade属性.这两个属性对关联关系都有影响 Invers ...