深入理解 Java 垃圾回收机制

问:简单说说 Java 的 JVM 内存结构分为哪几个部分

答:JVM 内存共分为虚拟机栈、堆、方法区、程序计数器、本地方法栈五个部分,分别解释如下。

  • 虚拟机栈:线程私有的,每个方法在执行时会创建一个栈帧,用来存储局部变量表、操作数栈、动态连接、方法返回地址等;其中局部变量表用于存放 8 种基本数据类型(boolean、byte、char、short、int、float、long、double)和 reference 类型。每个方法从调用到执行完毕对应一个栈帧在虚拟机栈中的入栈和出栈。

  • 堆:线程共享的,在虚拟机启动时创建,用于存放对象实例。

  • 方法区:线程共享的,用于存储已被虚拟机加载的类信息、常量、静态变量等。

  • 程序计数器:线程私有的,是当前线程所执行的字节码行号指示器,每个线程都有一个独立的程序计数器,字节码解释器工作时通过改变它的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理和线程恢复都依赖于它。

  • 本地方法栈:线程私有的,主要为虚拟机用到的 native 方法服务,与虚拟机栈类似。

 

问:简单说说堆和栈各自的特点

答:栈是一种具有后进先出性质的数据结构,也就是说后存放的先取,先存放的后取。堆是一种经过排序的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。由于堆的这个特性,常用来实现优先队列,堆的存取是随意的。

垃圾回收机制中的算法:

1.引用计数法:无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.

 2 标记-清除算法:采用从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,会造成内存碎片

3 标记-整理算法:采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针,进行了对象的移动,因此成本更高

4 copying算法 :克服句柄的开销和解决堆碎片的垃圾回收,它将堆分成对象面和空闲区域面,在对象面与空闲区域面的切换过程中,程序暂停执行

5 generation(分代)算法:不同生命周期的对象可以采取不同的回收算法,以便提高回收效率(jvm常见的垃圾回收器,分别针对新生代和旧生代实现不同的垃圾回收)

   a:年轻代 : 年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象 :采用 复制

   b :年老代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中 :年老代适合使用标记-清除算法(或者标记-清除-整理)

jvm触发主GC(Garbage Collector)的条件

1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用

2)Java堆内存不足时,GC会被调用

减少GC开销的措施

(1)不要显式调用System.gc():增加主GC的频率,也即增加了间歇性停顿的次数

(2)尽量减少临时对象的使用

(3)对象不用时最好显式置为Null

(4)尽量使用StringBuffer,而不用String来累加字符串

(5)能用基本类型如Int,Long,就不用Integer,Long对象:基本类型变量占用的内存资源比相应对象占用的少得多

(6)尽量少用静态对象变量:静态变量属于全局变量,不会被GC回收,它们会一直占用内存

(7)分散对象创建或删除的时间  

原文地址:https://www.cnblogs.com/eryun/p/7359556.html