【转】.net框架读书笔记---CLR内存管理\垃圾收集(四)

弱引用

  当一个根指向一个对象时,该对象不可能被垃圾收集器收集,在这种情况下,通常说存在一个该对象的强引用(strong reference)。垃圾收集器还支持弱引用(weak reference)的概念。弱引用允许垃圾收集器收集对象,同时也允许应用程序访问该对象,结果取决于时间。

  如果对象的弱引用存在,那么在垃圾收集执行后,该对象的内存将被执行清理。另一方面,要访问一个弱引用对象,应用程序必须获取该对象的一个强引用。如果应用程序在对象被执行之前得到了它的强引用,那么垃圾收集器将不再对该对象执行垃圾收集,因为这时存在一个该对象的强引用。

  下面代码展示了弱引用的使用

class Program
{
static void Main( string [] args)
{
SomeWeakReferenceMethod();
SomeStrongtReferenceMethod();
}

static void SomeWeakReferenceMethod()
{
// 创建一个强引用对象
SomeClass o = new SomeClass();

WeakReference wr = new WeakReference(o);

o = null ; // 移除对象的强引用

o = wr.Target as SomeClass;

if (o == null )
{
// 出现过垃圾回收,对象的内存已经被回收
Console.WriteLine( " 已经被回收 " );
}
else
{
// 未出现垃圾回收
Console.WriteLine( " 没有被回收 " + o.X.ToString());
}

}
static void SomeStrongtReferenceMethod()
{
// 创建一个强引用对象
SomeClass o = new SomeClass();
o = null ; // 移除对象的强引用
try
{
Console.WriteLine(o.X);
}
catch
{
Console.WriteLine( " error " );
}
}


}

public class SomeClass
{
private int x;

public int X
{
get
{
return this .x;
}
}

public SomeClass()
{
x = 5 ;
}
}

个人感觉弱引用机制有点像缓存,将一些操作起来比较费时(比如便利系统的硬盘)的东西第一次获取之后暂时放入缓存中,并且将其引用置为null来减少应用程序的压力,但是放置在缓存中可以再次使用(减少读取时的压力),至于是否能够再次使用成功要看垃圾收集器。如果执行过垃圾收集,弱引用的对象将会被回收掉当然就无法再次使用了。

  System.WeakReference有两个公用构造器:

  • public WeakReference(object target);
  •  public WeakReference(object target, bool trackResurrection);

  target表示要追踪的对象(上例中为SomeClass), trackResurrection表示是否要追踪对象的复苏,换句话说就是对象在执行Finalize方法后,是否还要追踪该对象(对象执行Finlize后对象复苏了) 。

  将不追踪对象复苏的WeakReference称为短弱引用(short weak reference),而将追踪对象复苏的称为长弱引用(long weak reference)。如果一个对象没有Finalize方法,长短弱引用是一样的,最好不要使用长弱引用,因为长弱引用在一个对象被执行终止后允许该对象复苏,将会导致对象的状态不可预知。

  一旦创建了对象的弱引用,通常将该对象的强引用设置为null,为了再次使用该对象,需要将弱引用转换为一个强引用,通过WeakReference的Target属性来完成的。如果target为null,那么对象已经被执行了垃圾收集,否则将会得到该对象的强引用。这时对象将不会被垃圾收集器收集了。

弱引用的内部机理

  需要再次探究托管堆。托管堆中包含了两个内部数据结构来管理弱引用。即短弱引用表和长弱引用表。这两个表包含着一些指针,他们引用着托管堆对象。

  当创建一个WeakReference对象时,它会在两个弱引用表中选择一个(长短弱引用相应对应),并在其中寻找一个空白插槽。该插槽的值将被设为我们希望追踪对象的地址---也就是new WeakReference构造的那个对象的地址,弱引用表将不会认为是应用程序的根,否则垃圾收集器将不能收集它们中的指针引用的对象。

  垃圾收集器运行时发生的一系列事情:

  • 垃圾收集器构造一个可达对象的图(.net框架读书笔记---CLR内存管理\垃圾收集(一));
  • 垃圾收集器扫描短弱引用表,如果表中的对象不是前面可达对象图的一部分(对象已经不是根,在上面的例子中o已经被置为null了),那么表示该对象是一个不可达的对象,将短弱引用表中对应插槽的值将被设置为null(Target为null了);
  • 垃圾收集器扫描终止化链表(.net框架读书笔记---CLR内存管理\垃圾收集(二))。如果该链表中指针引用的对象不是可达对象图的一部分,那么该对象将是不可达对象,它将被从终止化链表转移到终止化可达队列上。这时对象由成为可达对象图的一部分了。
  • 垃圾收集器扫描长弱引用表,如果表中的对象不是前面可达对象图的一部分(该图现在已经包括终止化可达队列中引用的对象了),那么表示该对象是一个不可达的对象,将长弱引用表中对应插槽的值将被设置为null(Target为null了);
  • 垃圾收集器压缩内存,填充不可达对象空出的位置。

  继续分析代码

if (o == null )
{
// 出现过垃圾回收,对象的内存已经被回收
Console.WriteLine( " 已经被回收 " );
}
else
{
// 未出现垃圾回收
Console.WriteLine( " 没有被回收 " + o.X.ToString());
}

因为在此之前o已经被置为null了,所以它已经是一个不可达对象,如果执行垃圾收集器,o自然不在可达对象图中,那么垃圾收集器将会将短弱引用表中插槽对应的值设为null,这样Target将返回null,上面代码自然会执行if里面的代码。如果垃圾收集器还没有执行,虽然o已经为null,但是短弱引用插槽依然保存着对象的引用,那么Target将会返回对象的引用,使对象继续可达,可以使用,当然上面代码就会执行else里面的代码。

  短弱引用并不追踪对象的复苏。只要垃圾收集器判断对象成为不可达的对象,它就会把短弱引用表中对应的指针设置为null。如果对象重写了Finalize方法,那么这时该方法还没有被调用,所以对象仍然存在。此时target仍然返回null,虽然这时对象已经进入终止化可达队列,对象仍然存在。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1756冗余_AB冗余模块1756-RM

AB冗余模块1756-RM100-C30UKJ01100-C30UKJ10100-C30UKL00100-C30UKL10AB冗余模块1756-RM100-C30UKP00100-C30UL00AB冗余模块1756-RM100-C30UL10100-C30UN00AB冗余模块1756-RM100-C30UN10100-C30UP001756-RM ControLogix冗余模块140U-H-RM12B 140U塑壳断路器外部附件1756-RMC1 C…

【转】.net框架读书笔记---CLR内存管理\垃圾收集(五)

对象复苏 当一个终止化对象被认为死亡时,垃圾收集器可以强制使该对象获得重生(进入终止化可达队列),因为这样才能调用对象的Finalize方法。在Finalize方法被调用之后,它才算真正的死亡了,一个终止化对象会经…

imp命令导入指定表_Oracle—— 导入/导出 数据:exp,imp 命令

exp,imp 命令是需要在windows 的 cmd 命令中执行的命令,主要用于数据的导入和导出工作,方便高效。远程地址—— ip:port/orcl 注:该远程地址不写,就意味着执行本地的库。Oracle的数据导出(1)导出数据的…

【转】.net框架读书笔记---CLR内存管理\垃圾收集(六)

对象代龄 代龄是旨在提高垃圾收集器性能的一种机制。有以下几点: 对象越新,其生存期越短;对象越老,其生存期越长;对托管堆的一部分执行垃圾收集要比对整个托管堆执行垃圾收集速度要快。在托管堆初始化时,其…

MySQL数据库开发理念_mysql之数据库基本理念

数据储存的问题:数据冗余和不一致数据访问困哪数据孤立完整性原子性问题例如AB2个账户,从A中向B转钱,不管如何转,A和B的总量是保持不变的。只要A减少,B就增加。并发访问异常安全性问题文件的分层:表示层&am…

【转】.net框架读书笔记---CLR内存管理\垃圾收集(七)

编程控制垃圾收集器 System.GC类型为应用程序提供了直接控制垃圾收集器的一些方法,可以通过GC.MaxGeneration来查询托管堆支持的最大代龄,目前为2。 通过下面方法执行垃圾收集器 GC.Collect(int);传递代龄,传递0,收集0代&#xff…

少年自学python笔记_自学python 笔记

print() 输入input() 输出python能够处理的数据类型:整数、浮点数、字符串("\"转义符,\n 换行)、布尔值/布尔代数(True、False(and【或】、or【于】、not【非】))(and:只有所有都为True,and运算结果才为True)(or:只要一个为True,or…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 1

前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 这篇文章我们将介绍一些方…

java解析string_java读取文件内容为string字符串的方法

直接就把项目中的方法贴出来吧/*** 读出城市列表文件*/private String readCityFile() {File file02 new File(path_xinfu, "/cityList.json");FileInputStream is null;StringBuilder stringBuilder null;try {if (file02.length() ! 0) {/*** 文件有内容才去读文…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 2

前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 继续上篇未完成的“参数传…

java 引用被回收_java GC 静态List 如果没有引用会被回收吗

垃圾收算法1.引用计数法(Reference Counting Collector)2.tracing算法(Tracing Collector)3.compacting算法(Compacting Collector)4.copying算法(Coping Collector)5。generation算法(Generational Collector)6.adaptive算法(Adaptive Collector)一个新的对象被创建&#xff0…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第五节 引用类型复制问题及用克隆接口ICloneable修复

前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 这一节我们将介绍引用类型…

linux virt java_Linux下Java环境安装

本节主要讲解Linux(Centos 6.5)下Java环境的安装1. 卸载机器上默认安装的JDK在Linux环境下一般会默认安装jdk,为了自己项目的开发部署,一般情况要重新装jdk,而且自己装的Jdk相对来说易控制版本,稳定性更高。所以以下是我卸载预装J…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第六节 理解垃圾回收GC,提搞程序性能****

前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外,了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 这一节我们将介绍垃圾回…

java下拉列表 动态_【示例】教你简单用Java写一个动态更新的下拉列表(无数据库)...

动态更新下拉列表varxmlHttp;functioncreatXMLHttpRequest(){if(window.ActiveXObject){xmlHttpnewActiveXObject("Microsoft.XMLHTTP");}else if(window.XMLHttpRequest){xmlHttpnewXMLHttpRequest();}}functionupdateSelect(){varselecteddocument.all.slt1.value;…

【转】分布式事务的常见解决方案

一、事务起步 1. 什么是事务 事务这种东西大家都耳熟能详了,通常指由一组操作组成的一个工作单元,这一整个组合要么全部成功,要么全部失败。 2. 本地事务 在计算机系统中,更多的是通过关系型数据库来控制事务,这是…

深入解析java web_java进阶--深入分析java Web

第一章: 深入了解Web请求整理本书的内容与之前的采用相同的方式,主要目的还是为了可以仔细的阅读。整理自己的见解。这本书整体的感觉很好,思路很清晰,最近就发现,国人写的文字和外国译文相差很大,主要体现…

【转】修饰符new将父类中的该方法隐藏掉有什么意义 不隐藏有什么弊端

这是一个C#语法的问题。子类如果要重写父类的方法的话,virtual-override一定成对的。 子类不重写,而是创建一个属于自己的同名方法,就最好加个new。如果不加new也等于new,但是编译器都会提醒你,加个标识比较好。 区别见…

java s.charat_Java中s.charAt(index)用于提取字符串s中的特定字符操作

charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.如: str.charAt(0)检索str中的第一个字符,str.charAt(str.length()-1)检索最后一个字符.警告:在字符串s中越界访问字符…

【转】.NET框架简介

.NET 框架是由微软开发的软件开发平台,其最主要的两个组成部分是公共语言运行时 (CLR) 和框架类库 (FCL),基础类库 (BCL)是框架类库的一个子集。 .NET 框架简介 下图展示了 .NET 框架的主要结构。 其中,最下层的无疑就是操作系统了。 在 …