Java 内存回收机制——GC机制

一、Java GC 概念说明

  Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop)的保证JVM中的内存空间,防止出现内存泄露和溢出问题。

  Java GC机制主要完成3件事:确定哪些内存需要回收,确定什么时候需要执行GC,如何执行GC。下面我们将从4个方面学习Java GC机制,1,内存是如何分配的;2,如何保证内存不被错误回收(即:哪些内存需要回收);3,在什么情况下执行GC以及执行GC的方式;4,如何监控和优化GC机制。

二、Java内存区域划分

  了解Java GC机制,必须先清楚在JVM中内存区域的划分。在Java运行时的数据区里,由JVM管理的内存区域分为下图几个模块:

1. 程序计数器(Program Counter Register)

程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。

每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的。

如果程序执行的是一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是一个本地(native,由C语言编写完成)方法,则计数器的值为Undefined,由于程序计数器只是记录当前指令地址,所以不存在内存溢出的情况,因此,程序计数器也是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域。

2. Java虚拟机栈(Java Virtual Machine Stacks)

一个线程的每个方法在执行的同时,都会创建一个栈帧(Statck Frame),栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法被调用时,栈帧在JVM栈中入栈,当方法执行完成时,栈帧出栈。

局部变量表中存储着方法的相关局部变量,包括各种基本数据类型,对象的引用,返回地址等。在局部变量表中,只有long和double类型会占用2个局部变量空间(Slot,对于32位机器,一个Slot就是32个bit),其它都是1个Slot。需要注意的是,局部变量表是在编译时就已经确定好的,方法运行所需要分配的空间在栈帧中是完全确定的,在方法的生命周期内都不会改变。

虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过多数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的),所以线程可以一直申请栈,直到内存不足,此时,会抛出OutOfMemoryError(内存溢出)。

每个线程对应着一个虚拟机栈,因此虚拟机栈也是线程私有的。

3. 本地方法栈(Native Method Stacks)

本地方法栈在作用,运行机制,异常类型等方面都与虚拟机栈相同,唯一的区别是:虚拟机栈是执行Java方法的,而本地方法栈是用来执行native方法的,在很多虚拟机中(如Sun的JDK默认的HotSpot虚拟机),会将本地方法栈与虚拟机栈放在一起使用。

本地方法栈也是线程私有的。

4. 堆区(Heap)

堆区是理解Java GC机制最重要的区域,没有之一。在JVM所管理的内存中,堆区是最大的一块,堆区也是Java GC机制所管理的主要内存区域,堆区由所有线程共享,在虚拟机启动时创建。堆区的存在是为了存储对象实例,原则上讲,所有的对象都在堆区上分配内存(不过现代技术里,也不是这么绝对的,也有栈上直接分配的)。

一般的,根据Java虚拟机规范规定,堆内存需要在逻辑上是连续的(在物理上不需要),在实现时,可以是固定大小的,也可以是可扩展的,目前主流的虚拟机都是可扩展的。如果在执行垃圾回收之后,仍没有足够的内存分配,也不能再扩展,将会抛出OutOfMemoryError:Java heap space异常。

5. 方法区(Method Area)

方法区是各个线程共享的区域,用于存储已经被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。

方法区在物理上也不需要是连续的,可以选择固定大小或可扩展大小,并且方法区比堆还多了一个限制:可以选择是否执行垃圾收集。一般的,方法区上执行的垃圾收集是很少的。但这也不代表着在方法区上完全没有垃圾收集,其上的垃圾收集主要是针对常量池的内存回收和对已加载类的卸载。

在方法区上进行垃圾收集,条件苛刻而且相当困难,效果也不令人满意,所以一般不做太多考虑,可以留作以后进一步深入研究时使用。

在方法区上定义了OutOfMemoryError:PermGen space异常,在内存不足时抛出。

三、Java对象的访问方式

一个Java的引用访问涉及到3个内存区域:JVM栈,堆,方法区。

以最简单的本地变量引用:Object obj = new Object()为例:

  • Object obj表示一个本地引用,存储在JVM栈的本地变量表中,表示一个reference类型数据;
  • new Object()作为实例对象数据存储在堆中;
  • 堆中还记录了Object类的类型信息(接口、方法、field、对象类型等)的地址,这些地址所执行的数据存储在方法区中;

在Java虚拟机规范中,对于通过reference类型引用访问具体对象的方式并未做规定,目前主流的实现方式主要有两种:

1. 通过句柄访问:

通过句柄访问的实现方式中,JVM堆中会专门有一块区域用来作为句柄池,存储相关句柄所执行的实例数据地址(包括在堆中地址和在方法区中的地址)。这种实现方法由于用句柄表示地址,因此十分稳定。

2. 通过直接指针访问:

通过直接指针访问的方式中,reference中存储的就是对象在堆中的实际地址,在堆中存储的对象信息中包含了在方法区中的相应类型数据。这种方法最大的优势是速度快,在HotSpot虚拟机中用的就是这种方式。

新生代、老年代、永久代:这三个类型的GC形式后续再进行总结,目前就写到这里  // TODO

目前需要仔细研究一下:https://www.zhihu.com/question/53613423

四、参考资料

《JAVA编程思想》第5章;

《Java深度历险》Java垃圾回收机制与引用类型;

《深入理解Java虚拟机:JVM高级特效与最佳实现》,第2-3章;

成为JavaGC专家Part II — 如何监控Java垃圾回收机制, http://www.importnew.com/2057.html

JDK5.0垃圾收集优化之--Don‘t Pause,http://calvin.iteye.com/blog/91905

【原】java内存区域理解-初步了解,http://iamzhongyong.iteye.com/blog/1333100

关于施用full gc频繁的分析及解决:http://www.07net01.com/zhishi/383213.html

原文地址:https://www.cnblogs.com/renhui/p/8762640.html

时间: 2024-10-10 15:24:41

Java 内存回收机制——GC机制的相关文章

Java 内存区域和GC机制-java概念理解

推荐几篇关于java内存介绍的文章 Java 内存区域和GC机制 http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html Jstatd方式远程监控Linux下 JVM运行情况 http://www.aiuxian.com/article/p-3218924.html 用Zabbix通过JMX方式监控weblogic http://www.huilog.com/?p=688 消息队列 http://kb.cnblogs.com

Java内存区域和GC机制篇

Java内存区域和GC机制一.目录 1.Java垃圾回收概括 2.Java内存区域 3.Java对象的访问方式 4.Java内存访问机制 5.Java GC 机制 6.Java垃圾收集器 二.Java垃圾回收概括 1.Java GC 介绍: a) Garbage Collection 垃圾收集.垃圾回收机制: b) Java中不需要编写内存回收和垃圾清理代码,也不需要考虑内存泄漏和溢出的问题: c) 因为在Java虚拟机中存在自动内存管理和垃圾清理机制: d) 该机制会对JVM(Java 虚拟机

Java笔记-Java 内存区域和GC机制

此次主要做一下java内存区域和GC机制的知识小结,下面的段落部分摘自网络,部分摘自书籍,具体的链接忘记了,因为这是之前学习的时候做下的笔记.还望原作者多多包涵! 1 Java垃圾回收 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机(JVM)中,存在自动内存管理和垃圾清扫机制.概括地说

Java 内存区域和GC机制

目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对 JVM(Java Virtual M

Java 内存区域和GC机制(转)

Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop

Java内存区域和GC机制

Java内存区域 了解Java GC机制,必须先清楚在JVM中内存区域的划分.在Java运行时的数据区里,由JVM管理的内存区域分为下图几个模块: 其中: 1,程序计数器(Program Counter Register):程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器.字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令. 每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的. 如

Java 内存区域和GC机制--备用

Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop

java内存管理与GC机制(一)

计算机cpu运转速度越来越快,硬盘远远跟不上cpu的读写速度,就设计可内存.随着cpu的发展,内存的读写速度也跟不上cpu处理速度,就在每颗cpu上加入了高速缓存.在多处理器系统中,每个处理器有自己的高速缓存,同时又共享内存(主存),这就有了缓存一致性问题.于是引入了一些协议,各个处理器运行时都要遵循,保证数据的一致性. Java中通过多线程机制使得多个任务同时执行处理,所有的线程共享JVM内存区域main memory,而每个线程又单独的有自己的工作内存,当线程与内存区域进行交互时,数据从主存

移动端测试===Android内存泄露和GC机制(转)

本文转自:https://www.testwo.com/article/1153 1.前言 Hello,小伙伴们,相信大家在项目测试中都遇到过内存泄露问题,小编也着实爬过很多坑.比如小编所测项目,更换了多实例版本的sdk,横竖屏切换后有MapView没有销毁,导致内存泄露.小编测试手表项目,因为手表内存有限,测试中常遇到应用无响应或者闪退,故而小编对GC机制进行了进一步学习了解. 本文先对Android内存垃圾回收机制进行介绍,之后对分析.定位内存泄露常用的测试方法进行总结,分享给大家. 2.A

Java 内存模型及GC原理

转至:http://blog.csdn.net/ithomer/article/details/6252552 一个优秀Java程序员,必须了解Java内存模型.GC工作原理,以及如何优化GC的性能.与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能. 本文将从JVM内存模型.GC工作原理,以及GC的几个关键问题进行探讨,从GC角度提高Java程序的性能. 一.Java内存模型 按照官方的说法:Java 虚拟机具