...

Callwoola

大雄'blog

Home 主页 Blog 博客 Tag标签 GitHub开源 about me关于我


jvm 垃圾回收原理

学习Java GC机制,可以帮助我们在日常工作中排查各种内存溢出或泄露问题,解决性能瓶颈,达到更高的并发量,写出更高效的程序。

我们将从4个方面学习Java GC机制,

Java GC机制主要完成3件事:确定哪些内存需要回收,确定什么时候需要执行GC,如何执行GC。

1,程序计数器(Program Counter Register):

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

2,虚拟机栈(JVM Stack)

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

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

3,本地方法栈(Native Method Statck):

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

4,堆区(Heap):

堆区是理解Java GC机制最重要的区域,没有之一。 在JVM所管理的内存中,堆区是最大的一块, 堆区也是Java GC机制所管理的主要内存区域, 堆区由所有线程共享,在虚拟机启动时创建。

堆区的存在是为了存储对象实例, 原则上讲,所有的对象都在堆区上分配内存 (不过现代技术里,也不是这么绝对的,也有栈上直接分配的)。

5,方法区(Method Area):

在Java虚拟机规范中,将方法区作为堆的一个逻辑部分来对待, 但事实上,方法区并不是堆(Non-Heap); 另外,不少人的博客中, 将Java GC的分代收集机制分为3个代:

这些作者将方法区定义为“永久代”,这是因为, 对于之前的HotSpot Java虚拟机的实现方式中, 将分代收集的思想扩展到了方法区,并将方法区设计成了永久代。 不过,除HotSpot之外的多数虚拟机,并不将方法区当做永久代, HotSpot本身,也计划取消永久代。 本文中,由于笔者主要使用Oracle JDK6.0, 因此仍将使用永久代一词。

6,直接内存(Direct Memory):

直接内存并不是JVM管理的内存, 可以这样理解,直接内存,就是JVM以外的机器内存,比如, 你有4G的内存,JVM占用了1G,则其余的3G就是直接内存, JDK中有一种基于通道(Channel)和缓冲区(Buffer) 的内存分配方式, 将由C语言实现的native函数库分配在直接内存中, 用存储在JVM堆中的DirectByteBuffer来引用。

由于直接内存收到本机器内存的限制, 所以也可能出现OutOfMemoryError的异常。

Java对象的访问方式

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

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

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

Java内存分配机制 堆区(Heap)

Minor GC

对象被创建时,内存的分配首先发生在年轻代 (大对象可以直接被创建在年老代)

“停止-复制(Stop-and-copy)”清理法(将Eden区和一个Survivor中仍然存活的对象拷贝到另一个Survivor中),

在Eden区,HotSpot虚拟机使用了两种技术来加快内存分配。分别是bump-the-pointer和TLAB(Thread-Local Allocation Buffers),这两种技术的做法分别是:

收集器

  • 文档信息:
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 发表日期: 2015-01-1522:10:50+0800
  • 更多内容:
  • Feed订阅:
相关内容:

disqus评论区:

0