`

6、内存管理机制---垃圾收集器(上)

 
阅读更多

       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过程),如果完成了线程就继续执行,否则就等待。

 

 

分享到:
评论

相关推荐

    C#内存管理机制C#内存管理机制

    此外,C#内存管理机制还可以帮助程序员更好地理解垃圾收集器的工作原理,并避免垃圾收集器带来的性能问题。 C#内存管理机制是C#编程语言中的一种机制,旨在帮助程序员更好地管理内存资源。了解C#内存管理机制可以...

    java内存管理白皮书-英文版

    ### Java内存管理概述 ...为了深入了解Java内存管理和垃圾收集器的工作原理,建议参考Sun Microsystems提供的官方文档和其他技术资源。此外,还可以探索社区论坛和技术博客,获取更多的实践经验和技巧。

    Java的内存管理机制分析

    ### Java的内存管理机制分析 #### 一、Java内存区域划分 Java的内存管理机制将内存分为以下几个区域: 1. **栈(Stack)**: - 存储局部变量(如基本类型的变量和对象的引用)。 - 每个线程拥有一个独立的栈。 ...

    JVM初探- 内存分配、GC原理与垃圾收集器

    JVM内存管理是Java虚拟机的核心机制之一,其主要包含对象的创建、内存分配、...通过对内存分配策略、对象生死判定、垃圾收集算法和垃圾收集器的理解与应用,可以更好地掌握JVM的内存管理,从而提升应用性能和稳定性。

    计算机科学与技术-外文翻译-外文文献-英文文献-Java垃圾收集器的工作方式.doc

    总的来说,Java垃圾收集器通过自动化内存管理,既提高了对象创建的效率,又降低了内存管理的复杂性,是Java平台的一大优势。理解垃圾收集的工作机制对于编写高效、健壮的Java应用程序至关重要。开发者可以通过调整...

    漫谈Java垃圾收集器.pdf

    Java垃圾收集器是Java虚拟机(JVM)中的一种自动内存管理机制,旨在释放程序员从手动内存管理的繁琐工作中解脱出来。垃圾收集器通过跟踪对象的引用关系,确定哪些对象是可以被释放的,然后将其回收,以避免内存泄露...

    NET解密--深入理解.NET垃圾收集机制参照.pdf

    .NET框架提供了几个关键方法来与垃圾收集器交互,如`GC.Collect()`用于强制执行垃圾收集,`GC.WaitForPendingFinalizers()`等待所有终结器执行完毕,`GC.GetTotalMemory(true)`获取应用程序使用的总内存等。...

    JVM-内存管理 2012-12.pdf

    对Java开发人员而言,理解这些内存管理机制不仅能够帮助其编写出更加稳定和高效的代码,还能在发生内存问题时迅速定位和解决问题。随着JDK版本的更新,内存管理的机制和参数也在不断地优化和演进,开发者需要不断...

    Sun_JDK_1.6内存管理--实现篇-毕玄

    它采用了更先进的垃圾收集器,如实时垃圾收集器(Real Time GC),能够在保证低延迟的情况下进行垃圾收集,非常适合对响应时间有严格要求的应用场景。此外,JRockit还提供了更精细的内存管理工具和监控能力,帮助...

    7种JVM垃圾收集器特点-优劣势-及使用场景.pdf

    JVM垃圾收集器是Java虚拟机(JVM)中的一种自动内存管理机制,负责回收Java程序中不再使用的对象,以避免内存泄漏和提高程序性能。Java中有多种垃圾收集器,每种垃圾收集器都有其特点、优劣势和使用场景。 1. ...

    Sun JDK 1.6内存管理--调优篇

    G1是新一代的垃圾收集器,目标是实现可预测的暂停时间模型。 针对内存调优,我们需要关注以下几点: 1. 合理设置堆大小:根据应用的内存需求,设置-Xms和-Xmx参数来控制堆的初始和最大大小,避免因内存不足导致的...

    Java垃圾收集机制解析:自动内存管理的艺术

    本文将深入探讨Java中的垃圾收集机制,包括其工作原理、不同类型的垃圾收集器以及它们在实际应用中的使用。 Java语言的一大卖点是它提供了自动内存管理,这意味着程序员不需要手动分配和释放内存,从而减少了内存...

    垃圾收集机制的基本原理及方法word版

    - **垃圾收集器**:JVM使用不同的垃圾收集器策略,如分代收集、标记-清除、复制、标记-压缩等,来优化内存管理。分代收集将堆分为年轻代和老年代,以适应不同生命周期的对象。 - **可达性分析**:垃圾收集器通过...

    Java垃圾收集必备手册

    Java 垃圾收集是 Java 语言中的一种自动内存管理机制,旨在释放不再使用的内存资源,以避免内存泄漏和提高程序性能。在这篇手册中,我们将深入探究 Java 垃圾收集的基础知识,包括垃圾收集的定义、垃圾收集算法、...

    Java的垃圾收集器(GC)

    总之,垃圾收集器是Java生态系统中不可或缺的一部分,深入理解和合理运用GC机制,对于构建高效、稳定的Java应用程序至关重要。随着Java技术的不断演进,GC也将持续优化,为开发者带来更加便捷的开发体验。

    对象的释放和垃圾收集机制.txt

    在Java等语言中,对象的释放通常由垃圾收集器自动完成,但在C++等语言中,则需要程序员手动进行管理。 ##### Java中的对象释放 Java通过一种名为垃圾收集(Garbage Collection, GC)的机制来管理内存。GC会在适当的...

    如何实现一个垃圾收集器 - 知乎1

    在本文中,我们将探讨如何实现一个简单的垃圾收集器,这是一个基础的自动化内存管理系统,主要针对Java环境。垃圾收集器是现代编程语言运行时系统的关键组件,负责自动管理内存,回收不再使用的对象以避免内存泄漏。...

    性能工程师指南:玩转OpenJDK HotSpot垃圾收集器

    5. **内存层面**:特别关注Java虚拟机(JVM)中的内存管理机制,如垃圾收集(GC)过程。 #### 四、Java虚拟机(JVM)性能工程 Java虚拟机(JVM)是运行Java程序的核心组件之一,它负责将Java字节码转换为特定平台的机器...

    c#内存检测工具-----

    同时,理解C#内存管理机制,结合实际的检测结果,有助于编写更高效、资源友好的代码。对于大型或复杂项目,定期进行内存分析和优化是必要的,以确保应用程序在长时间运行后仍能保持良好的性能。

    JVM内存模型和垃圾收集.pdf

    本文将基于“JVM内存模型和垃圾收集”的主题,深入探讨JVM中的内存管理机制以及垃圾收集的相关技术细节。 #### 二、JVM内存模型概述 JVM内存模型主要涉及以下几个关键概念: 1. **堆(Heap)** - **定义**:堆是...

Global site tag (gtag.js) - Google Analytics