Java虚拟机之垃圾回收详解一

Java虚拟机之垃圾回收详解一

Java技术和JVM(Java虚拟机)

一、Java技术概述:

  Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布。它是Java程序的技术基础,这些程序包括:实用程序、游戏、商业应用程序。在全世界范围内,Java运行在超过数十亿台个人计算机上,数十亿台设备上,还包括手机和电视设备。Java由一系列的关键组件作为一个整体构建出了Java平台。

Java Runtime Edition

  当你下载Java,你就得到了Java运行环境(JRE)。JRE包括Java虚拟机(JVM)、Java平台核心类文件、支持Java平台的类库。对于运行Java程序,这三个部分都是必须的。

Java Programming Language

  Java是一门面向对象编程语言,具有以下特性:

  1. 跨平台的:Java程序执行过程中首先被编译成字节码,这些字节码被存储在类文件中然后装载到JVM中。(这里插一句:字节码是什么?javap命令反编译.class文件)由于程序运行在JVM中,而非直接运行在操作系统上,所以Java程序可以运行在多种操作系统和设备上。
  2. 面向对象的:Java是一种面向对象语言,它继承的很多C/C++的特性,并在此基础上做了改进。
  3. 垃圾自动回收机制:Java程序自动分配和回收内存,使得编程人员无需担心垃圾回收问题。
  4. 丰富的标准库:Java有大量的预先做好的对象提供给编程人员,更便捷的完成输入/输出、网络编程、日期计算等任务。

Java Development Kit

  JDK是Java程序开发的工具集,你可以使用它编译用Java语言编写的程序,然后在JVM上运行你编写的程序。另外,JDK还提供打包和发布程序功能。

  JDK和JRE共享Java程序编程接口(Java API)。Java API 是Java供开发人员编写Java程序时使用的预打包库,Java API 提供工具使得Java程序开发更容易,比如字符串操作、日期/时间处理、网络编程、实现数据结构(例如:链表,maps、堆栈、队列)。

Java Virtual Machine

  JVM是一台抽象的计算机。JVM是一个程序,这个程序看起来像是一台计算机,它可以执行程序。通过这种方式,Java程序的编写使用了相同的接口和库。每种JVM对应着特定的操作系统,将Java指令转换为可以在该操作系统上运行的指令或是命令。通过这种方式,Java程序实现了平*立性。

  其实JVM对Java语言是一无所知的,JVM能识别的是特殊的二进制格式和类文件格式。一个类文件包含了JVM指令或者字节码、符号表、以及一些辅助信息。

  为了安全起见,JVM对于类文件中的编码的语法和结构有严格的规定。However, any language with functionality that can be expressed in terms of a valid class file can be hosted by the Java virtual machine. Attracted by a generally available, machine-independent platform, implementors of other languages can turn to the Java virtual machine as a delivery vehicle for their languages.(这几句话不太理解,暂时放在这里吧!)

二、探索JVM的结构:

Hotspot Architecture

  HotSpot JVM 的架构使得它能支持强大的基础特性和性能,并且能够实现高性能和较好的扩展性。例如,HotSpot JVM JIT编译器可以在编译时进行动态优化。换言之,这些编译器可以在Java程序运行时做出最优选择,生成高性能的本地主机指令以适应本地主机系统架构。另外,它的运行环境和多线程垃圾回收变的越来越成熟,越来越具有持久的工程性,HotSpot JVM 在大型计算机系统上也表现出可扩展性。

Java虚拟机之垃圾回收详解一

  JVM 主要的组件包括:类加载器、运行时数据区、执行引擎。

Key Hotspot Components

  JVM 跟性能相关的主要组件如下图中高亮部分。

 Java虚拟机之垃圾回收详解一

  JVM中有三个组件和性能密切相关。堆是对象数据存储区,这个区域由垃圾回收管理。大多数调试性能和堆的大小有关,也和选择合适的垃圾回收器相关。JIT 编译器对性能影响很大,但很少需要调试新版本的JVM。

垃圾回收概述

什么是垃圾自动回收?

  垃圾自动回收是一个查看堆内存的过程,在此过程中辨识出那些对象仍在使用,哪些对象不再使用然后删除不会再被使用的对象。一个的对象或者对象引用正在使用的意思是程序的某个部分仍然保持着一个指针指向这个对象或对象的引用。一个不再使用的对象或引用意思是不再被程序的任何部分所引用。所以未被引用的对象所占的内存空间是可以被回收的。

  在C语言中,分配和回收内存是用户手动操作的,在Java语言中,内存回收是由垃圾回收器自动完成的。垃圾回收基本过程:

  步骤1:标记

  第一步是标记。这个过程是垃圾回收器标记出那片内存在使用,那片不在使用。

  Java虚拟机之垃圾回收详解一

  蓝色表示被引用对象,金色表示未被引用对象。在做出这个标记阶段,所有对象都被扫描一遍(如此操作,效率必然很低啊)。如果系统中的所有对象都需要被扫描一遍是一个很耗时的过程。

  步骤2:普通删除

  普通删除是删除未被引用的对象,保留被引用对象并且使用指针指向删除后的空闲空间。

  Java虚拟机之垃圾回收详解一

  内存回收器保存了空闲块的地址引用来分配给新的对象使用。

  步骤2a:压缩删除

  为了进一步改善性能,在删除未被引用对象后,压缩空间里剩余的被引用对象。通过移动被引用对象在一起,使得空闲空间聚合在一起,更便于新的内存分配。

  Java虚拟机之垃圾回收详解一

为什么分代垃圾回收?

  如之前所述,标记和压缩JVM中的所有对象是效率很低的。随着越来越多的对象被分配空间,对象链表越来越大使得垃圾回收时间越来越长。然而,根据对程序分析的经验表明,大多数对象的生命周期很短。

  如下图数据所示,Y轴代表被分配的字节数,X代表随时间推移被回收的字节数。

  Java虚拟机之垃圾回收详解一

  如你所见,随着时间推移保留在内存中的对象越来越少。实际上,大多数对象的生命周期都很短,如图所示,X轴左侧有很大的值,短时间内巨幅下降。

JVM中的分代

  从对象分配的动作中得到的信息可以用来改善JVM的性能。因此,堆可以被分为更小的块或是分代。堆可分成:新生代、老或者是年老代和永久代。

  Java虚拟机之垃圾回收详解一

  新生代存储了所有的新建对象。当新生代溢出时,触发minor garbage collection。在假定对象高死亡率的情况下,Minor collections 是最优的垃圾回收选择。一个充满废弃对象的新生代内存空间回收很快。某些存留的对象年龄增加然后移动到Old Gerneration。

  Stop the World Event - 所有 minor garbage collection 都是 ”stop the world“ 事件,即是所有的线程都会被停止直到垃圾回收操作完成。

  Old Gerneration 用来存储长时间存活的对象。典型的,JVM会为新生代设置一个阈值,当新生代年龄达到此阈值,此对象会被移动到old generation。即使old generation 也需要被回收。old generation 被回收事件叫做 major garbage collection 。

  major garbage collection 也是 stop the world事件。通常 major garbage collection 会更慢,该过程包括所有的存活对象。所以对于响应式的程序,major garbage collection 需要最小化。同样需要注意,major garbage collection 所引起的 stop the world事件的时间长度受Old Gerneration空间所采用的垃圾回收器的类别影响。

  永久代存储了元数据,这些元数据是JVM用来描述程序中所使用的类文件和方法的。old Gerneration 存储了JVM运行时所依赖的类。另外,Java SE 类库文件和方法也可能存储在这里。

  类文件也可能被回收,如果JVM发现他们不再被需要,回收的空间用于存储哪些程序所必须的类。所有的垃圾回收都会对永久代空间进行收集。

分代垃圾收集过程

  既然已经理解了堆分代的原因,现在来看一下不同空间如何相互影响的。下图描述了JVM中对象分配内存和对象老龄化的过程:

  1.首先,任何新对象分配到eden 空间。两个survivor空间开始时均为空。

  Java虚拟机之垃圾回收详解一

  2.当eden 空间溢出时,minor garbage collection 被触发。

  Java虚拟机之垃圾回收详解一

  3.被引用的对象被移动到第一个survivor空间。当eden 空间被清空时未被引用的对象被删除。

    Java虚拟机之垃圾回收详解一

  4.下一次minor GC时,eden空间执行相同动作。未被引用对象被删除,被引用对象移动到一个survivor空间。然而,在这种情况下,被引用对象移动到S1中。另外,由上次minor GC产生的存储在S0中的对象年龄增加并且移动到S1中。一旦所有存活对象都被移动到S1中,S0和eden空间都被清空。注意到,现在在survivor空间中有不同年龄的对象。

  Java虚拟机之垃圾回收详解一

  5.下一次minor GC时,重复同样的过程。然而,这次survivor空间互换了。被引用对象移动到了S0。存活对象年龄增加,eden 和 S1 被清空。

  Java虚拟机之垃圾回收详解一

  6.下面说明的是一次升级过程。在一次minor GC之后,当老年代的对象的年龄达到特定年龄阈(这个例子中阈值是8)时,这些对象从新生代升级成ld generation。

  Java虚拟机之垃圾回收详解一

  7.随着minor GC继续发生,对象继续被移动到old generation 空间。

  Java虚拟机之垃圾回收详解一

  8.young generation 经过多次的minor GC 之后,最终,major GC 会在 old  generation 上执行以清理并压缩此内存空间。

  Java虚拟机之垃圾回收详解一

总结:以上就是垃圾回收的基本原理和过程,有错误之处请指正!

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

  

上一篇:JAVA中使用log4j及slf4j进行日志输出的方法详解


下一篇:Java日志系统及框架分析