Grabage Collection      GC
GC要完毕的三件事情:
哪些内存须要回收?
什么时候回收?
怎样回收?
内存运行时区域的各个部分中:
程序计数器、虚拟机栈、本地方法栈这3个区域随线程而生。随线程而灭。
栈中的栈帧随着方法的进入和退出而有条不紊地运行着出栈和入栈的操作。

每个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此,
这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需过多考虑回收的问题。
由于方法结束或者线程结束时。内存自然就跟着回收了。
java堆和方法区就不一样了。一个接口中多个实现类须要的内存可能不一样。一个方法中的多个
分支须要的内存也可能不一样,我们仅仅有在程序处于运行期间才知道会创建哪些对象,这部分内存的分配和回收是动态的。
我们的垃圾收集器所关注的就是这部分内存。
堆内存中存放这大量对象实例,垃圾收集器首先要推断这些对象哪些是“活着的”哪些是“死去的”
引用计数器算法
给对象中加入一个引用计数器,每当被引用时,该计数器就加1。失去引用时计算器减一。

不论什么时刻,计算器值为0就代表该对象是不能再被使用的。
存在的问题:非常难解决对象间循环引用的问题
可达性分析算法
基本思想:通过一系列的称为"GC Roots"的对象作为起点。从这些节点開始向下搜索,搜索所走过的路径称为
引用链(Reference Chain),当一个对象到GC Roots没有不论什么引用链相连时,则证明此对象是不可用的。

java中。可作为GC Roots的对象包含以下几种:
1、虚拟机栈(栈帧中的本地变量表)中引用的对象
2、方法区中类静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中(即一般说的Native方法)引用的对象
不管哪种算法都是和引用有关的,可是引用该怎样理解呢?
什么样的引用算是实用的,什么样的引用又是没用的呢?
在JDK1.2后对引用进行了区分。这四种引用强度依次逐渐递减:
强引用
     指在程序总普遍存在的,如:Object obj = new Object(),这类引用。仅仅要强引用还在。垃圾收集器永远不会回收掉被引用的对象。
软引用
     用来描写叙述一些还实用可是非必须的对象。对于软引用关联着的对象。系统会在发生内存溢出异常之前,将会把这些对象列入回收范围之中进行二次回收。假设这次回收后还没有足够的内存才会抛出内存溢出异常
弱引用
     弱引用也是用来描写叙述一些非必须对象的。它的强度比软引用更弱一些,被弱引用关联的对象。仅仅能存活到下一次垃圾收集发生之前。

不管当前内存是否足够,都会被垃圾收集器回收掉。

虚引用
     又称为幽灵引用或者幻影引用。

一个对象是否有虚引用的存在。全然不会对其生存时间构成影响,也无法通过一个虚引用来取得一个对象的实例。

为一个对象设置虚引用的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。

生存还是死亡
在可达性分析算法中。即使不可达的对象。也不一定是死亡的。要真正确定一个对象的死亡,至少要经历俩次标记的过程:
第一次标记:
     对象在进行可达性分析后发现没有和GC Roots相连接的引用链
     而且进行了一次筛选。筛选的条件是该对象有没有必要运行finalize()方法
          当该对象没有重写finalize()方法,或者finalize()方法已经被虚拟机运行过,则觉得没有必要运行finalize()方法
          当该对象须要运行finalize()方法,则会被放进一个叫做F-Queue的队列,由虚拟机自己主动运行
第二次标记:
     finalize()方法是对象逃脱死亡的最后一次机会,GC会对F-Queue队列进行第二次标记。
     假设对象在finalize()方法中成功解救自己:
          仅仅要与引用链上的不论什么一个对象建立关系就能够。

     那么第二次标记,它将被移除即将回收的集合。假设该对象这个阶段还没有逃脱,那么它就被回收了。
以下是代码。原书上的内容:
package com.smile.three;

/**
* 此代码演示了两点:
* 1.对象能够在被GC时自我解救。
* 2.这样的自救的机会仅仅有一次。由于一个对象的finalize()方法最多仅仅会被系统自己主动调用一次
* @author 深入理解JVM作者周志明zzm
*/
public class FinalizeEscapeGC { //定义对象
public static FinalizeEscapeGC SAVE_HOOK = null; //活着的对象能够调用的方法
public void isAlive() {
System.out.println("yes, i am still alive :)");
} //重写finalize()方法
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize mehtod executed!finalize方法被运行了");
FinalizeEscapeGC.SAVE_HOOK = this;
} public static void main(String[] args) throws Throwable {
//创建对象并赋值
SAVE_HOOK = new FinalizeEscapeGC(); //对象第一次成功解救自己
SAVE_HOOK = null;
System.gc();
// 由于Finalizer方法优先级非常低,暂停0.5秒,以等待它
Thread.sleep(500);
if (SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("no, i am dead :(");
} // 以下这段代码与上面的全然同样,可是这次自救却失败了
SAVE_HOOK = null;
System.gc();
// 由于Finalizer方法优先级非常低,暂停0.5秒,以等待它
Thread.sleep(500);
if (SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("no, i am dead :(");
}
}
}

注意一点:
不论什么一个对象的finalize()方法都仅仅会被系统运行一次。

所以在第二次回收的时候。它的finalize()方法就失效了。

回收方法区
方法区,在分代算法中被称为永久代,而在永久代进行GC要比新生代的回收"性价比"要低非常多。
永久代垃圾回收的内容:
     废弃常量:
          没有不论什么引用,进入常量池的常量,甚至常量池中的常量也可能被回收。

     没用的类:
          没用的类标准:
          1、该类全部的实例都被回收,java堆中不存在不论什么该类的实例。
          2、载入该类的ClassLoader已经被回收
          3、该类相应的java.lang.Class对象没有在不论什么地方被引用,无法在不论什么地方通过反射訪问该类的方法。

GC回收涉及内容较多,我还在学习其中,这个系列博客会持续更新。

《深入理解java虚拟机》学习笔记四/垃圾收集器GC学习/一的更多相关文章

  1. 《深入理解Java虚拟机》笔记03 -- 垃圾收集器

    收集器可以大致分为:单线程收集器, 并发收集器和并行收集器. 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态. 并发(Concurrent):指用户线程与垃圾收集 ...

  2. 深入理解Java虚拟机 第三章 垃圾收集器 笔记

    1.1   垃圾收集器 垃圾收集器是内存回收的具体实现.以下讨论的收集器是基于JDK1.7Update14之后的HotSpot虚拟机.这个虚拟机包含的所有收集器有: 上图展示了7种作用于不同分代的收集 ...

  3. 深入理解java虚拟机(五)垃圾收集器

    垃圾收集器 垃圾收集器是垃圾收集算法的具体实现.Java规范对垃圾收集器的实现没有做任何规定,因此不同的虚拟机提供的垃圾收集器可能有很大差异.HotSpot虚拟机1.7版本使用了多种收集器.如下图. ...

  4. 深入理解java虚拟机(2)------垃圾收集器和内存分配策略

    GC可谓是java相较于C++语言,最大的不同点之一. 1.GC回收什么? 上一篇讲了内存的分布. 其中程序计数器栈,虚拟机栈,本地方法栈 3个区域随着线程而生,随着线程而死.这些栈的内存,可以理解为 ...

  5. 《深入理解Java虚拟机》笔记02 -- 垃圾收集算法

    1. 标记 - 清除算法 先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.它是最基础的收集算法.其他收集算法都是根据其思路,改进其不足之处. 缺点:1) 标记和清除两个阶段的效率都不 ...

  6. [Note][深入理解Java虚拟机] 第三章 垃圾收集器与内存分配策略笔记

    书上关于GCTimeRatio的讲解有点难以理解,查看Oracle的文档后重新理解了下 -XX:GCTimeRatio 运行时间 / GC时间 当GCTimeRatio为19时,运行时间是GC时间的1 ...

  7. java之jvm学习笔记四(安全管理器)

    java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...

  8. 《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具

    虚拟机性能监控与故障处理工具 详解 4.1 概述 本文参考的是周志明的 <深入理解Java虚拟机> 第四章 ,为了整理思路,简单记录一下,方便后期查阅. JDK本身提供了很多方便的JVM性 ...

  9. 深入理解Java虚拟机 -- 读书笔记(1):JVM运行时数据区域

    深入理解Java虚拟机 -- 读书笔记:JVM运行时数据区域 本文转载:http://blog.csdn.net/jubincn/article/details/8607790 本系列为<深入理 ...

随机推荐

  1. [POI2008]KUP-Plot purchase(单调队列)

    题意 给定k,n,和n*n的矩阵,求一个子矩形满足权值和在[k,2k]之间 , 题解 这里用到了极大化矩阵的思想.推荐论文<浅谈用极大化思想解决最大子矩阵问题>Orz 如果有一个元素在[k ...

  2. Python对象的循环引用问题

    目录 Python对象循环引用 循环引用垃圾回收算法 容器对象 生成容器对象 追踪容器对象 结束追踪容器对象 分代容器对象链表 何时执行循环引用垃圾回收 循环引用的垃圾回收 循环引用中的终结器 pyt ...

  3. Android基础新手教程——4.3.2 BroadcastReceiver庖丁解牛

    Android基础新手教程--4.3.2 BroadcastReceiver庖丁解牛 标签(空格分隔): Android基础新手教程 本节引言: 上节我们对BroadcastReceiver已经有了一 ...

  4. Linux系统编程——进程间通信:信号中断处理

    什么是信号? 信号是 Linux 进程间通信的最古老的方式.信号是url=474nN303T2Oe2ehYZjkrggeXCaJPDSrmM5Unoh4TTuty4wSgS0nl4-vl43AGMFb ...

  5. ListView阻尼效果

    效果图省略.. . activity_main.xml(仅仅有一个自己定义ListView) <RelativeLayout xmlns:android="http://schemas ...

  6. Python使用Redis实现一个简单作业调度系统

    Python使用Redis实现一个简单作业调度系统 概述 Redis作为内存数据库的一个典型代表,已经在非常多应用场景中被使用,这里仅就Redis的pub/sub功能来说说如何通过此功能来实现一个简单 ...

  7. Launcher3实现壁纸居中

    Launcher3的wallpaper显示是动态的,与Launcher预置桌面数目有关,让壁纸居中,仅仅能确保第一次开机时壁纸居中,后面用户改动桌面数目后,就无法达到了.怎样要在默认桌面数目配置时居中 ...

  8. Xcode加入应用图标以及启动界面

    寻找了许久的资料,记录下Xcode加入应用图标以及启动界面的学习笔记: 很实用的网址: 1.(苹果官网)Designing for iOS 2.iOS 8 人机交互指南 图标和图片的尺寸參考: 更加具 ...

  9. POJ 1611 The Suspects 并查集 Union Find

    本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每 ...

  10. Cordic 算法入门

    三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来计算任意角度的三角函数的值.这种表格在人们刚刚产生三角函数的概念的时候就已经有了,它们通常是通过从已知值(比如sin(π/2)= ...