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 在大型计算机系统上也表现出可扩展性。

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

Key Hotspot Components

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

 

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

垃圾回收概述

什么是垃圾自动回收?

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

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

  步骤1:标记

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

  

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

  步骤2:普通删除

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

  

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

  步骤2a:压缩删除

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

  

为什么分代垃圾回收?

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

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

  

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

JVM中的分代

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

  

  新生代存储了所有的新建对象。当新生代溢出时,触发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空间开始时均为空。

  

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

  

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

    

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

  

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

  

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

  

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

  

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

  

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

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

  

Java虚拟机之垃圾回收详解一的更多相关文章

  1. 每日一问:讲讲 Java 虚拟机的垃圾回收

    昨天我们用比较精简的文字讲了 Java 虚拟机结构,没看过的可以直接从这里查看: 每日一问:你了解 Java 虚拟机结构么? 今天我们必须来看看 Java 虚拟机的垃圾回收算法是怎样的.不过在开始之前 ...

  2. 基于Python对象引用、可变性和垃圾回收详解

    基于Python对象引用.可变性和垃圾回收详解 下面小编就为大家带来一篇基于Python对象引用.可变性和垃圾回收详解.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. 变量不是盒子 在示例所示 ...

  3. Java虚拟机之垃圾回收

    简述 Java与那些较传统的语言比如C++有个很大不同就是垃圾回收策略了.前者通常是虚拟机自动帮我们做了,而后者就需要我们手动来完成. Java虚拟机帮我们完成了垃圾回收,是不是意味着我们就不用完全去 ...

  4. Java 虚拟机 - GC 垃圾回收机制分析

    Java 垃圾回收(Garbage Collection,GC) Java支持内存动态分配.垃圾自动回收,而 C++ 不支持.我想这可能也是 为什么 Java 脱胎于 C++ 的一个原因吧. GC 的 ...

  5. 【java虚拟机】垃圾回收机制详解

    作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/6486852.html 一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分 ...

  6. java虚拟机之垃圾回收算法

    标记-清除算法: 这是最基础的,就是之前所讲的两次标记,首先标记出所有 需要回收的对象,然后进行统一清除, 这有两缺点:一是效率低,标记和清除(开启低优先级进行回收)都是低效率的.第二是空间问题,标记 ...

  7. 深入理解java虚拟机【垃圾回收算法】

    Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...

  8. Java虚拟机:内存模型详解

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实 ...

  9. java虚拟机 之 垃圾回收机制

    一.如何判断对象已死 垃圾回收器并不是java独有的,垃圾回收器的作用就是回收对象释放内存空间,那么如何判断哪些对象应该被回收呢? 在Java语言中是采用GC Roots来解决这个问题.如果一个对象和 ...

随机推荐

  1. 怎么在Linux上下载并安装ESET NOD32 Antivirus 4桌面版

    转自:怎么在Linux上下载并安装ESET NOD32 Antivirus 4桌面版 下载并安装ESET NOD32 Antivirus 4的Linux桌面版,根据下面的步骤一步一步的来: I.  下 ...

  2. ASP.NET页面周期

    上图为ASP.NET页面生命周期图. 以下详细讲解一下ASP.NET的页面生命周期.   请求页 请求页发生在页生命周期之前.用户请求时,ASP.NET将确定是否需要分析和编译页面,或者是否可以在不运 ...

  3. Maven 镜像

    http://mvnrepository.com/http://search.maven.org/http://repository.sonatype.org/content/groups/publi ...

  4. php学习之路

    1.php拼接字符串+查询 $floor_id = M('house_floor_input')->where($map1)->field('id')->select(); $flo ...

  5. windows下安装mysql笔记

    接着上几篇文章再来看下windows下安装mysql. 我这里是windows7 64位, 安装过程中还是遇到一些坑,这里记录下. 一.下载安装包 打开mysql官网下载页面:http://dev.m ...

  6. Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)

    通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...

  7. 在QT中使用Irrlicht引擎的方法与步骤

      Ø 相关库,插件安装部分 本篇文档介绍在Qt5.2.0下面使用lrrlicht引擎在Qt窗口中输出(开发环境:vs2012) 1. 首先安装好Qt5.2.0,下载地址: http://downlo ...

  8. eclipse  sae上传代码

    eclipse  sae上传代码http://www.sinacloud.com/doc/sae/java/tools.html#eclipse 来自为知笔记(Wiz)

  9. ubuntu下 使用AB做压力测试

    1最近刚开始接触apache大数据下数据优化,讲一下apache 下ab压力测试工具. 程序“ab”尚未安装. 您可以使用以下命令安装: apt-get install apache2-utils 以 ...

  10. kafak 命令使用

    本篇文章主要内容: kafka常用命令总结 一.kafka常用命令总结: 1.创建topic bin/kafka-topics.sh --create --zookeeper ip:port/chro ...