博文重点:

    学习目标:哪些内存需要回收

         什么时候回收

            如何回收

    在基于概念讨论的模型中,主要对Java堆和方法区进行讨论。

    why?:一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样。只有在程序运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,gc关注的就是这一块内存。

哪些内存需要回收:

        判断对象是否存活:

                引用计数算法:对象中添加一个引用计数器,有一个地方引用它则计数器加1,引用失效时,减1。引用为0的对象就是不可使用的。

                  优点:实现简单,判定效率高。

                  缺点:无法解决对象之间的循环引用,见代码。

 public class ReferenceCountingGC {
public Object instance = null; private static final int _1MB = 1024 * 1024; private byte[] bigSize = new byte[2 * _1MB]; public static void testGC() {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA; objA = null;
objB = null; // 虽然引用计数都为1,但内存还是被回收了,说明采用的不是引用计数算法
System.gc();
} public static void main(String[] args) {
testGC();
}
}

                可达性分析算法:思路,选择一系列称为"GC Roots"的对象作为起始点,从这些节点向下搜索,走过的路就称为引用链。如果一个对象无法通过引用链到达"GC roots",则证明该对象不可用,则可被回收。

                  可作为GC Roots的对象:虚拟机栈中引用的对象,方法区类静态属性引用的对象,方法区中常量引用的对象,Nativa方法中引用的对象。 todo:理解gc roots

    引用:

      todo:各种应用场景

      引用细化定义:当内存空间还足够,则能保留在内存中。如果内存空间进行垃圾收集之后还是非常紧张,则抛弃这些对象。

      基于这样的需求,扩充了引用的概念。

      强引用:只要强引用存在,就永远不会被gc。eg. Object obj = new Object();

      软引用:内存充足时不会回收,不足时被回收。jvm将这个软引用加入到与之关联的引用队列

      弱引用:无论内存是否充足,都会进行回收。jvm将这个弱引用加入到与之关联的引用队列

      虚引用:

    

    对象的两次标记:如果对象在进行第一次可达性分析之后,没有到gc roots到引用链,则进行第一次标记。并进入第一次自救过程,如果该对象重写了finalize()方法时 && finalize()方法没有被虚拟机调用过,则会执行finalize()方法进行自救过程,将该对象放入到一个F-Queue到队列中,由虚拟机自动建立的,低优先级的Finalize线程去执行(但是不保证会等待方法运行结束,为了效率考虑)。如果在finalize()方法中将该对象的引用赋值给了类变量或成员变量,重新建立起了可达关系,则在该第二次标记过程会被移出"即将回收"集合,自救成功,但要注意,这样的自救只能执行一次。

    

 public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive() {
System.out.println("yes , i am still alive");
} @Override
protected void finalize() throws Throwable {
System.out.println("finalize method excute!");
FinalizeEscapeGC.SAVE_HOOK = this;
} public static void main(String[] args) throws InterruptedException {
SAVE_HOOK = new FinalizeEscapeGC(); // 第一次拯救自己成功
SAVE_HOOK = null;
System.gc(); Thread.sleep(500);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("dead");
} // 第二次拯救自己失败,只能执行一次
SAVE_HOOK = null;
System.gc(); Thread.sleep(500);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("dead");
}
}
}

    方法区(永久代)的回收:主要回收废弃常量和无用类。

                废弃常量:eg:"abc"存在常量池中,但没有其它地方引用这个常量,类,方法,字段的符号引用也和这个类似。

                无用类:该类所有实例已被回收

                    加载该类的ClassLoader已被回收

                    对应的Class对象没有被引用,无法在其它地方通过反射访问该类的方法。

                      满足了这些条件的类可以被回收,是否进行回收,取决于我们对虚拟机的参数设置情况。

                使用场景:在大量使用反射,动态代理,CGLib等频繁定义自ClassLoader的场景都需要虚拟机具备类卸载的功能

深入理解java虚拟机---垃圾收集器和分配策略-1的更多相关文章

  1. 深入理解java虚拟机----->垃圾收集器与内存分配策略(下)

    1.  前言 内存分配与回收策略 JVM堆的结构分析(新生代.老年代.永久代) 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保  2.  垃圾 ...

  2. 深入理解JAVA虚拟机 垃圾收集器和内存分配策略

    引用计数算法 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器都为0的对象就是不可能再被使用的 ...

  3. 深入理解JAVA虚拟机原理之内存分配策略(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 1.对象优先在Eden分配 大多情况,对象在新生代Eden区分配.当Eden区没 ...

  4. 深入理解java虚拟机笔记Chapter3-内存分配策略

    内存分配策略 新生代和老年代的 GC 操作 新生代 GC 操作:Minor GC 发生的非常频繁,速度较块. 老年代 GC 操作:Full GC / Major GC 经常伴随着至少一次的 Minor ...

  5. [深入理解Java虚拟机]<垃圾收集器与内存分配策略>

    Overview 垃圾收集考虑三件事: 哪些内存需要回收? 什么时候回收? 如何回收? 重点考虑Java堆中动态分配和回收的内存. Is Object alive? 引用计数法 给对象添加一个引用计数 ...

  6. 深入理解java虚拟机--垃圾收集器

    对象的销毁 对象的finalize方法只会执行一次,在finalize里可以自救不被销毁,二次被主动gc,必定会销毁 类销毁

  7. Java虚拟机垃圾收集器与内存分配策略

    Java虚拟机垃圾收集器与内存分配策略 概述 那些内存须要回收,什么时候回收.怎样回收是GC须要完毕的3件事情. 程序计数器.虚拟机栈与本地方法栈这三个区域都是线程私有的,内存的分配与回收都具有确定性 ...

  8. [转] 深入理解Java G1垃圾收集器

    [From] https://www.cnblogs.com/ASPNET2008/p/6496481.html 深入理解Java G1垃圾收集器 本文首先简单介绍了垃圾收集的常见方式,然后再分析了G ...

  9. 《深入理解 java 虚拟机》学习 -- 内存分配

    <深入理解 java 虚拟机>学习 -- 内存分配 1. Minor GC 和 Full GC 区别 概念: 新生代 GC(Minor GC):指发生在新生代的垃圾收集动作,因为 Java ...

随机推荐

  1. (22) java web的struts2框架的使用-struts配置文件

    1,配置文件的引用 struts中配置文件可以有多个,每个模块的包里面都可以单独设立一个struts配置文件. 主的配置文件,放在“src”文件夹下,可以引入其他配置文件,引入方式: <!-- ...

  2. caioj1097: [视频]树状数组1(快速求和计算) cdq分治入门

    这题虽然是个树状数组,但是也可以用cdq分治做啊~~,这个就是一个浅显的二维偏序的应用? cdq分治和普通的分治有什么区别? 举个栗子:有4个小朋友,你请他们吃饭,假如你分治搞,就会分成很多子问题—— ...

  3. YTU 2907: 类重载实现矩阵加法

    2907: 类重载实现矩阵加法 时间限制: 1 Sec  内存限制: 128 MB 提交: 345  解决: 164 题目描述 编写矩阵类Matrix,实现两个2x3矩阵相加.主函数已给定. 输入 两 ...

  4. SERVLET类常用接口及方法

    SERVLET类常用接口及方法 2011-09-09 16:14:43    [size=xx-small]SERVLET类常用接口及方法2007年04月05日 星期四 04:46 P.M.基本类和接 ...

  5. 【Codevs1346】HelloWorld编译器

    http://codevs.cn/problem/1346/ 可怜我战绩 // <1346.cpp> - 10/30/16 17:12:09 // This file is made by ...

  6. 整型变量修饰符,char类型数据存储原理,字节数,

    //------------------整型变量修饰符 修饰符(int short long longlong signed unsigned)所有修饰符都是用来修整形 int 4short %hd ...

  7. 用jQuery插件来提升SharePoint列表表单用户体验

    本文将描述如何通过简单的CSS和jQuery插件提升SharePoint默认的列表表单体验.这些小技巧并不仅仅改善了外观,还提升了可用性. 剩余字数 我们以通知列表为例.通知正文字段假设要求不应该超过 ...

  8. 使用VS进行打包程序解决生成两个文件的问题(压缩后只有一个exe)

    使用VS打包创建setup相信大家都挺熟的了,不熟的话网上也有很多,就不做介绍了,现在给大家写下怎么将生成的那些文件夹以及setup.exe和.msi 文件打包成一个exe 我们这里使用的是Winra ...

  9. eclipse集成lombok注解不起作用

    安装步骤: 步骤一:lombok的下载地址为:https://projectlombok.org/download,jar包很小.这里也把依赖写出来: <dependency> <g ...

  10. Postgresql空库发布或者部分空库,模式,表处理备份流程

    --备份数据库结构pg_dump -h localhost -p 8101 -d qhsoam -s -f /tmp/nodata.sql --仅备份某模式和该模式下的数据表结构pg_dump -h ...