1960年 MIT(麻省理工学院 Massachusetts Institute of Technology )Lisp语言 第一次使用动态内存分配和垃圾收集技术;
那些内存需要被释放
在什么时候释放
怎样实现释放
程序计数器、jvm栈、本地方法栈随 线程创建和释放(不由GC回收),栈中的栈帧随方法的进入和退出顺序执行入栈和出,每个栈帧的大小在编译时确定(无动态扩张情况);
垃圾收集器对堆回收前,判断对象在后面的程序还要被调用,或者不再被调用, 判断方法:
1、引用计算法:在调用时,计数器值+1;调用结束时,计数器值-1;当计数器值为0时不能再被调用,适用大部分gc算法;但不能解决对象循环互调;
2、可达性分析算法 通过"GC Roots"对象作为起始点,从起始节点开始向下搜索,走过的路径称为引用链(reference chain),当一个对象与GC Roots没有链接时,则该对象是不可用的。
可以作为GC Roots对象包括:
- jvm栈(栈中本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象 (单例模式 final A a;)
- JNI(c++)中引用的对象
1.2之后对引用进行看扩充,将引用分为:
强引用(String Reference),类似 A a = new A(),只要a还会使用,收集器不会收集a空间
软引用(Soft Reference), 弱引用被回收后,还是不能消除内存溢出,溢出前回收 软引用空间
弱引用(Weak Reference),下次gc收集垃圾时,被回收
虚引用(Phantom Reference);关联对象,在对象被回收之前返回一个系统信息,不能通过虚引用取得实例,该空间已被回收;
对象的自我救赎finalize()
一个对象被回收前至少要经历两次标记,可达性分析后发现与GC Roots没有连接时,将进行第一次标记, 并筛选该对象是否需要执行finalize()方法; 如果该对象被判定有必要执行finalize方法则将放入F-Queue列队,由低级Finalizer线程去触发它,finalize()提供给对象最后一次不回收的机会,只要和引用链上任何一个对象建立关联即可:
public class Test { public static Test t=null; public void isAlive(){ System.out.println("still here"); } protected void finalize(){ System.out.println("执行finalize方法"); t = this; //自我引用 } public static void main(String...s) throws Exception{ t = new Test(); t=null; System.out.println("is here ?"); System.gc(); //执行gc()时触发finalize()方法,finalize方法优先级很低,不设置等待,就会出现没有执行就执行下一条语句了; Thread.sleep(500); t.isAlive(); System.out.println(t.hashCode()); //执行了finalize()方法,t复活了,但只能复活一次,若再执行: t=null; System.out.println("is here ?"); System.gc(); Thread.sleep(500); //判定对象t是否还在heap中存在 System.out.println(t==null); } }
输出:
is here ?
执行finalize方法
still here //heap中还存在
5629279
is here ?
true //表示已被回收
原书作者不建议使用此方法复活对象;
回收方法区,jvm规范中讲过可以不要求jvm对方法区的垃圾回收,因为能释放的空间很少。永久代的垃圾收集主要有两部分:废弃常量和无用的类。
回收常量与回收heap类似,而回收无用的类比较复杂,判断是否为无用的类:
- java heap中不存在该类的任何实例
- 该类的类类加载已经被回收
- 该类的Class对象没有被任何地方引用
$垃圾收集算法:
标记-清除(Mark- sweep)
标记-整理(Mark- compact)
复制(Copying)
分代收集算法(老年代、新生代),新生代中98%的会被回收,将新生代分为Eden(大块)、两个survival;每次使用Eden和其中一个survival,当回收时,将Eden和survival中存活的对象一次性的复制到另外一块survival空间上,然后格式化Eden和刚才用过的survival空间,HotSpot默认Eden与survival大小比例8:1,新生代中的90%用来装载新生对象,10%用来转载存活的对象。
HotSpot的算法实现(详见下章):
枚举根节点:可达性分析必须在一个一致性的快照中进行-即整个分析期间,系统就像冻结了一样。否则如果一边分析,系统一边动态表化,得到的结果就没有准确性。这就导致了系统GC时必须停顿所有的Java执行线程。在HotSpot实现中,使用一组称为 OopMap 的数据结构来存放对象引用。OopMap会在类加载完成的时候,记录对象内什么偏移量上是什么类型的数据,在JIT编译过程中,也会在特定的位置记录下栈和寄存器哪些位置是引用。
安全点:OopMap内容变化的指令非常多,HotSpot并不会为每条指令都产生OopMap,只是在特定的位置记录了这些信息,这些位置成为“安全点”(SafePoint)。程序执行时只有在达到安全点的时候才停顿开始GC。一般具有较长运行时间的指令才能被选为安全点,如方法调用、循环跳转、异常跳转等。接下来要考虑的便是,如何在GC时保证所有的线程都“跑”到安全点上停顿下来。这里有两种方案:
抢先式中断 (Preemptive Suspension) 和主动式中断 (Voluntary Suspension)。
抢先式中断会把所有线程中断,如果某个线程不在安全点上,就恢复让它跑到安全点上。几乎没有虚拟机采用这种方式。
主动式中断思想是设立一个GC标志,各个线程会轮询这个标志并在需要时自己中断挂起。这样,标志和安全点是重合的。
安全区域:Safepoint机制可以保证某一程序在运行的时候,在不长的时间里就可以进入GC的Safepoint。但是如果程序没有分配CPU时间,例如处于Sleep状态或者Blocked状态,这时候线程无法响应JVM的中断请求。对于这种情况,只能用 安全区域 (Safe Region)来解决。安全区域是指在一段代码片段之中,引用关系不会发生变化。在这个区域中任意地方开始都是安全的。在线程执行到Safe Region中的代码时,就标记自己已经进入了Safe Region,这样JVM在发起GC时就跳过这些线程。在线程要离开Safe Region时,它要检查系统是否已经完成了枚举(或GC过程),如果完成了线程就继续执行,否则就等待。
相关推荐
Java自动内存管理机制包含两部分:内存分配和内存回收,要想理解内存分配和回收的机制,则需要了解下Java内存区域(Java运行时数据区),这篇随笔将按照下面的线索进行逐步解析:1.Java运行时数据区2.对象“已死”的...
对实际编程来说,理解您的内存管理器的能力与局限性至关重要。在大部分系统语言中,比如 C 和 C++,您必须进行内存管理。本文将介绍手工的、半手工的以及自动的内存管理实践的基本概念。 追溯到在 Apple II 上...
10.2 对C++垃圾收集器的需求 10.3 在编译器中还是在库中 10.4 保守式垃圾收集 10.5 准复制式收集器 10.6 智能指针 10.6.1 在没有智能指针类层次的情况下进行转换 10.6.2 多重继承 10.6.3 不正确的转换 10.6.4 某些...
文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...
知识点覆盖范围:垃圾回收算法、垃圾收集器、GC原理、垃圾回收的优缺点等。 难度级别:从基础到高级,面试官可能会深入探讨垃圾回收的细节和实现原理。 实践经验:理论知识之外,面试官可能会问到实际场景下的优化...
理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。 垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是...
原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。 JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以...
重庆交通大学信息科学与工程学院 课程...Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)、多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再...
为此,垃圾收集器会按照固定的时间间隔(或代码执行中预设的收集时间),周期性的执行这一操作。 下面我们来分析一下函数中局部变量正常的生命周期。局部变量只在函数执行的过程中存在。而在这个过程中,
10.2 对C++垃圾收集器的需求 10.3 在编译器中还是在库中 10.4 保守式垃圾收集 10.5 准复制式收集器 10.6 智能指针 10.6.1 在没有智能指针类层次的情况下进行转换 10.6.2 多重继承 10.6.3 不正确的转换 10.6.4 某些...
为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间)周期性地执行这一操作。 垃圾收集的方式: 1.标记清除(mark-and-sweep) 最常用的垃圾收集方式。当变量进入环境时,就将变量标记为“进入...
垃圾收集机制的原理很简单:找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔,或代码执行中预定的收集时间,周期性地执行这一操作 局部变量只在函数执行的过程中存在。而在...
为此,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间), 周期性地执行这一操作。 具体到浏览器中的实现,则通常有两个策略,分别为标记清除和引用计数。 一、标记清除 JavaScript 中最常用的垃圾...
垃圾收集器GC管理 虚拟机GC垃圾回收收集算法(内存回收方法论) 虚拟机GC垃圾回收收集器(内存回收具体实现) 对象内存分配 虚拟机性能监控与故障处理工具 内存溢出问题及调优 类文件结构 虚拟机类加载机制 编译期编译...
原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。 JavaScript垃圾回收的机制很简单:找出不再使用的变量,然后释放掉其占用的内存,但是这个过程不是实时的,因为其开销比较大,所以...
4. explorer-------打开资源管理器 5. logoff---------注销命令 6. shutdown-------60秒倒计时关机命令 7. lusrmgr.msc----本机用户和组 8. services.msc---本地服务设置 9. oobe/msoobe /a----检查XP是否激活 ...
最新jvm面试题合集,涵盖JVM运行时数据区、垃圾回收算法、...垃圾收集器可以根据不同的算法和策略进行配置和优化,以提高内存使用效率和性能。 类加载机制:JVM通过类加载器加载类文件,将其转换为可执行的二进制格式。
3. 自动内存管理:Java使用垃圾收集器(Garbage Collector)自动管理内存。开发者不需要手动进行内存分配和释放,通过“对象生命周期”的概念,垃圾收集器会自动回收不再使用的内存。 4. 异常处理:Java提供了异常...
3. 自动内存管理:Java使用垃圾收集器(Garbage Collector)自动管理内存。开发者不需要手动进行内存分配和释放,通过“对象生命周期”的概念,垃圾收集器会自动回收不再使用的内存。 4. 异常处理:Java提供了异常...