JAVA GC机制

如果无法正常显示,请先停止浏览器的去广告插件。
分享至:
1. JAVA GC 机制 殷佳玲
2. 目录 ■ Java 垃圾回收概况 ■ Java 内存区域 ■ Java 对象的访问方式 ■ Java GC 机制 ■ 垃圾收集器
3. Java 垃圾回收概况 在 Java 虚拟机中,存在自动内存管理和垃圾清扫机制。该机制对 JVM ( Java Virtual Machine )中的中的内存进行标记,并确定哪些内存需要回收,根据一定的回收 策略,自动的回收内存,永不停息的保证 JVM 中的内存空间,防止出现内存泄露和 溢出问题。 Java GC 机制主要完成 3 件事:确定哪些内存需要回收,确定什么时候需要执行 GC ,如何执行 GC 。经过这么长时间的发展, Java GC 机制已经日趋完善,几乎 可以自动的为我们做绝大多数的事情。然而,如果我们从事较大型的应用软件开发, 曾经出现过内存优化的需求,就必定要研究 Java GC 机制。
4. Java 内存区域
5. ■ 1 ,程序计数器( Program Counter Register )中的: 用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行 号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指 令。   每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有 一个程序计数器)中的的。   
6. ■ 2 ,虚拟机栈( JVM Stack )中的: 一个线程的每个方法在执行的同时,都会创建一个栈帧( Statck Frame )中的,栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法 被调用时,栈帧在 JVM 栈中入栈,当方法执行完成时,栈帧出栈。    每个线程对应着一个虚拟机栈,因此虚拟机栈也是线程私有的。
7. ■ 3 ,本地方法栈( Native Method Stack )中的:本地方法栈在作用,运行机制,异 常类型等方面都与虚拟机栈相同,唯一的区别是:虚拟机栈是执行 Java 方法 的,而本地方法栈是用来执行 native 方法的,在很多虚拟机中(如 Sun 的 JDK 默认的 HotSpot 虚拟机)中的,会将本地方法栈与虚拟机栈放在一起使用。  本地方法栈也是线程私有的。
8. ■ 4. 堆区( Heap )中的:堆区是理解 Java GC 机制最重要的区域。在 JVM 所管理的 内存中,堆区是最大的一块,堆区也是 Java GC 机制所管理的主要内存区域,堆 区由所有线程共享,在虚拟机启动时创建。堆区的存在是为了存储对象实例,原 则上讲,所有的对象都在堆区上分配内存(不过现代技术里,也不是这么绝对 的,也有栈上直接分配的)中的。 ■   一般的,根据 Java 虚拟机规范规定,堆内存需要在逻辑上是连续的(在物 理上不需要)中的,在实现时,可以是固定大小的,也可以是可扩展的,目前主流的 虚拟机都是可扩展的。如果在执行垃圾回收之后,仍没有足够的内存分配,也不 能再扩展,将会抛出 OutOfMemoryError:Java heap space 异常。
9. ■ 方法区( Method Area )中的   方法区是各个线程共享的区域,用于存储已经被虚拟机加载的类信息(即加载类 时需要加载的信息,包括版本、 field 、方法、接口等信息)中的、 final 常量、静态变 量、编译器即时编译的代码等。   方法区在物理上也不需要是连续的,可以选择固定大小或可扩展大小,并且方法 区比堆还多了一个限制:可以选择是否执行垃圾收集。一般的,方法区上执行的垃圾 收集是很少的,这也是方法区被称为永久代的原因之一 , 但这也不代表着在方法区上 完全没有垃圾收集,其上的垃圾收集主要是针对常量池的内存回收和对已加载类的卸 载。   
10. ■ 直接内存( Direct Memory )中的: 直接内存并不是 JVM 管理的内存,可以这样理解,直接内存,就是 JVM 以外 的机器内存,比如,你有 4GG 的内存, JVM 占用了 1GG ,则其余的 3G 就是直接 内存, JDK 中有一种基于通道( Channel )中的和缓冲区( Buffer )中的的内存分配方 式,将由 C 语言实现的 native 函数库分配在直接内存中,用存储在 JVM 堆中的 DirectByteBuffer 来引用。由于直接内存收到本机器内存的限制,所以也可能出 现 OutOfMemoryError 的异常。
11. Java 对象的访问方式 ■ 一般来说,一个 Java 的引用访问涉及到 3 个内存区域: JVM 栈,堆,方法区。 例如: Object obj = new Object() ; ■ Object obj 表示一个本地引用,存储在 JVM 栈的本地变量表中。 ■ Object() 作为实例对象数据存储在堆中; ■ 堆中还记录了 Object 类的类型信息(接口、方法、 field 、对象类型等)中的的地 址,这些地址所执行的数据存储在方法区中;
12. ■ 在 Java 虚拟机规范中,对于通过 reference 类型引用访问具体对象的方式并未做 规定,目前主流的实现方式主要有两种: ■ 1G. 通过句柄访问
13. ■ 2. 通过直接指针访问
14. Java 内存分配机制 ■ Java 内存分配和回收的机制概括的说,就是:分代分配,分代回收。对象将根据 存活的时间被分为:年轻代( Young Generation )中的、年老代( Old Generation )中的、永久代( Permanent Generation ,也就是方法区)中的。
15. ■ 年老代( Old Generation )中的:对象如果在年轻代存活了足够长的时间而没有被 清理掉(即在几次 Young GC 后存活了下来)中的,则会被复制到年老代,年老代的 空间一般比年轻代大,能存放更多的对象,在年老代上发生的 GC 次数也比年轻 代少。当年老代内存不足时,将执行 Major GC ,也叫 Full GC 。     如果对象比较大(比如长字符串或大数组)中的, Young 空间不足,则大对象会直 接分配到老年代上(大对象可能触发提前 GC ,应少用,更应避免使用短命的大对 象)中的。
16. Java GC 机制 ■ GC 机制的基本算法是:分代收集   我们可以发现,新生代中使用 1G 个大的 Eden 区和 2 个小的 Survivor 区   由于绝大部分的对象都是短命的,甚至存活不到 Survivor 中,所以, Eden 区与 Survivor 的比例较大, HotSpot 默认是 8:1G ,即分别占新生代的 80% , 1G0% , 1G0% 。如果一次回收中, Survivor+Eden 中存活下来的内存超过了 1G0% ,则需要将一部分对象分配到 老年代。
17. ■ 老年代:   老年代存储的对象比年轻代多得多,而且不乏大对象。一般,老年代用的算法是 标记 - 整理算法,即:标记出仍然存活的对象(存在引用的)中的,将所有存活的对象向 一端移动,以保证内存的连续。       在发生 Minor GC 时,虚拟机会检查每次晋升进入老年代的大小是否大于老 年代的剩余空间大小,如果大于,则直接触发一次 Full GC 。
18. ■ 方法区(永久代)中的:   永久代的回收有两种:常量池中的常量,无用的类信息。常量的回收很简单,没 有引用了就可以被回收。对于无用的类进行回收,必须保证 3 点: ■ 类的所有实例都已经被回收 ■ 加载类的 ClassLoader 已经被回收 ■ 类对象的 Class 对象没有被引用(即没有通过反射引用该类的地方)中的       永久代的回收并不是必须的,可以通过参数来设置是否对类进行回收。
19. 垃圾收集器 垃圾收集器要做的两件事: 1G. 正确检测垃圾对象 2. 释放垃圾对象占用的内存空间。
20. 在 GC 机制中,起重要作用的是垃圾收集器,垃圾收集器是 GC 的具体实现。
21. ■ CMS 收集器 CMS ( Concurrent Mark Sweep )中的收集器是一种以获取最短回收停顿时间为目 标的收集器。目前很大一部分的 Java 应用都集中在互联网站或 B/S 系统的服务端 上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好 的体验。 CMS 收集器的内存回收过程是与用户线程一起并发地执行。   缺点:产生大量空间碎片、并发阶段会降低吞吐量
22. ■ G1 收集器 ( 最前沿成果之一 ) 与 CMS 收集器相比 G1G 收集器有以下特点 : 1G. 空间整合: G1G 收集器采用标记整理算法,不会产生内存空间碎片。分配大对象 时不会因为无法找到连续空间而提前触发下一次 GC 。 2. 可预测停顿: G1G 能建立可预测的停顿时间模型,能让使用者明确指定在一个长 度为 N 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒,这几乎已经 是实时 Java 的垃圾收集器的特征了。
23. THANK YOU !

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.138.0. UTC+08:00, 2024-12-22 09:42
浙ICP备14020137号-1 $Map of visitor$