MS公开的gc.cs源码

此博客为转载内容,原文链接为https://www.cnblogs.com/wannaCNBLOGS/archive/2005/08/04/207072.html ,涉及runtime相关内容,但未给出具体信息。
None.gif// ==++==
None.gif
// 
None.gif
//   
None.gif
//    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
None.gif
//   
None.gif
//    The use and distribution terms for this software are contained in the file
None.gif
//    named license.txt, which can be found in the root of this distribution.
None.gif
//    By using this software in any fashion, you are agreeing to be bound by the
None.gif
//    terms of this license.
None.gif
//   
None.gif
//    You must not remove this notice, or any other, from this software.
None.gif
//   
None.gif
// 
None.gif
// ==--==
ExpandedBlockStart.gifContractedBlock.gif
/**//*============================================================
InBlock.gif**
InBlock.gif** Class:  GC
InBlock.gif**
InBlock.gif**                                        
InBlock.gif**
InBlock.gif** Purpose: Exposes features of the Garbage Collector through
InBlock.gif** the class libraries.  This is a class which cannot be
InBlock.gif** instantiated.
InBlock.gif**
InBlock.gif** Date:  November 9, 1998
InBlock.gif**
ExpandedBlockEnd.gif===========================================================
*/

ExpandedBlockStart.gifContractedBlock.gif
namespace System dot.gif{
InBlock.gif    
//This class only static members and doesn't require the serializable keyword.
InBlock.gif

InBlock.gif    
using System;
InBlock.gif    
using System.Security.Permissions;
InBlock.gif    
using System.Reflection;
InBlock.gif    
using System.Security;
InBlock.gif    
using System.Threading;
InBlock.gif    
using System.Runtime.CompilerServices;
InBlock.gif    
using System.Reflection.Cache;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <include file='doc\GC.uex' path='docs/doc[@for="GC"]/*' />
ExpandedSubBlockStart.gifContractedSubBlock.gif    public sealed class GC dot.gif{
InBlock.gif    
InBlock.gif        
// This class contains only static methods and cannot be instantiated.
ExpandedSubBlockStart.gifContractedSubBlock.gif
        private GC() dot.gif{
ExpandedSubBlockEnd.gif        }

InBlock.gif    
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern int GetGenerationWR(IntPtr handle);
InBlock.gif
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern long nativeGetTotalMemory();
InBlock.gif
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern void nativeCollectGeneration(int generation);
InBlock.gif
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern int nativeGetMaxGeneration();
InBlock.gif    
InBlock.gif        
// Returns the generation that obj is currently in.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.GetGeneration"]/*' />
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
public static extern int GetGeneration(Object obj);
InBlock.gif    
InBlock.gif        
// Forces a collection of all generations from 0 through Generation.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.Collect"]/*' />
ExpandedSubBlockStart.gifContractedSubBlock.gif        public static void Collect(int generation) dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (generation<0dot.gif{
InBlock.gif                
throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
ExpandedSubBlockEnd.gif            }

InBlock.gif            nativeCollectGeneration(generation);
ExpandedSubBlockEnd.gif        }

InBlock.gif    
InBlock.gif        
// Garbage Collect all generations.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.Collect1"]/*' />
ExpandedSubBlockStart.gifContractedSubBlock.gif        public static void Collect() dot.gif{
InBlock.gif            
//-1 says to GC all generations.
InBlock.gif
            nativeCollectGeneration(-1);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
InBlock.gif        
// This method DOES NOT DO ANYTHING in and of itself.  It's used to 
InBlock.gif        
// prevent an object from losing any outstanding references a touch too
InBlock.gif        
// early.  Users should insert a call to this method near the end of a
InBlock.gif        
// method where they must keep an object alive for the duration of that
InBlock.gif        
// method, up until this method is called.  Here is an example:
InBlock.gif        
// 
InBlock.gif        
// "dot.gifall you really need is one object with a Finalize method, and a 
InBlock.gif        
// second object with a Close/Dispose/Done method.  Such as the following 
InBlock.gif        
// contrived example:
InBlock.gif        
//
InBlock.gif        
// class Foo {
InBlock.gif        
//    Stream stream = dot.gif;
InBlock.gif        
//    protected void Finalize() { stream.Close(); }
InBlock.gif        
//    void Problem() { stream.MethodThatSpansGCs(); }
InBlock.gif        
//    static void Main() { new Foo().Problem(); }
InBlock.gif        
// }
InBlock.gif        
// 
InBlock.gif        
//
InBlock.gif        
// In this code, Foo will be finalized in the middle of 
InBlock.gif        
// stream.MethodThatSpansGCs, thus closing a stream still in use."
InBlock.gif        
//
InBlock.gif        
// If we insert a call to GC.KeepAlive(this) at the end of Problem(), then
InBlock.gif        
// Foo doesn't get finalized and the stream says open.
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.KeepAlive"]/*' />
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
public static extern void KeepAlive(Object obj);
InBlock.gif
InBlock.gif        
// Returns the generation in which wo currently resides.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.GetGeneration1"]/*' />
ExpandedSubBlockStart.gifContractedSubBlock.gif        public static int GetGeneration(WeakReference wo) dot.gif{
InBlock.gif            
return GetGenerationWR(wo.m_handle);
ExpandedSubBlockEnd.gif        }

InBlock.gif    
InBlock.gif        
// Returns the maximum GC generation.  Currently assumes only 1 heap.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.MaxGeneration"]/*' />
ExpandedSubBlockStart.gifContractedSubBlock.gif        public static int MaxGeneration dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn nativeGetMaxGeneration(); }
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.WaitForPendingFinalizers"]/*' />
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
public static extern void WaitForPendingFinalizers();
InBlock.gif    
InBlock.gif        
// Indicates that the system should not call the Finalize() method on
InBlock.gif        
// an object that would normally require this call.
InBlock.gif        
// Has the DynamicSecurityMethodAttribute custom attribute to prevent
InBlock.gif        
// inlining of the caller.
InBlock.gif
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
internal static extern void nativeSuppressFinalize(Object o);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.SuppressFinalize"]/*' />
InBlock.gif        public static void SuppressFinalize(Object obj)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (obj == null)
InBlock.gif                
throw new ArgumentNullException("obj");
InBlock.gif            nativeSuppressFinalize(obj);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Indicates that the system should call the Finalize() method on an object
InBlock.gif        
// for which SuppressFinalize has already been called. The other situation 
InBlock.gif        
// where calling ReRegisterForFinalize is useful is inside a finalizer that 
InBlock.gif        
// needs to resurrect itself or an object that it references.
InBlock.gif        
// Has the DynamicSecurityMethodAttribute custom attribute to prevent
InBlock.gif        
// inlining of the caller.
InBlock.gif
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern void nativeReRegisterForFinalize(Object o);
InBlock.gif        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.ReRegisterForFinalize"]/*' />
InBlock.gif        public static void ReRegisterForFinalize(Object obj)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
if (obj == null)
InBlock.gif                
throw new ArgumentNullException("obj");
InBlock.gif            nativeReRegisterForFinalize(obj);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
// Returns the total number of bytes currently in use by live objects in
InBlock.gif        
// the GC heap.  This does not return the total size of the GC heap, but
InBlock.gif        
// only the live objects in the GC heap.
InBlock.gif        
//
ExpandedSubBlockStart.gifContractedSubBlock.gif
        /**//// <include file='doc\GC.uex' path='docs/doc[@for="GC.GetTotalMemory"]/*' />
InBlock.gif        public static long GetTotalMemory(bool forceFullCollection)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
long size = nativeGetTotalMemory();
InBlock.gif            
if (!forceFullCollection)
InBlock.gif                
return size;
InBlock.gif            
// If we force a full collection, we will run the finalizers on all 
InBlock.gif            
// existing objects and do a collection until the value stabilizes.
InBlock.gif            
// The value is "stable" when either the value is within 5% of the 
InBlock.gif            
// previous call to nativeGetTotalMemory, or if we have been sitting
InBlock.gif            
// here for more than x times (we don't want to loop forever here).
InBlock.gif
            int reps = 20;  // Number of iterations
InBlock.gif
            long newSize = size;
InBlock.gif            
float diff;
ExpandedSubBlockStart.gifContractedSubBlock.gif            
do dot.gif{
InBlock.gif                GC.WaitForPendingFinalizers();
InBlock.gif                GC.Collect();
InBlock.gif                size 
= newSize;
InBlock.gif                newSize 
= nativeGetTotalMemory();
InBlock.gif                diff 
= ((float)(newSize - size)) / size;
ExpandedSubBlockEnd.gif            }
 while (reps-- > 0 && !(-.05 < diff && diff < .05));
InBlock.gif            
return newSize;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern MethodBase nativeGetCurrentMethod(ref StackCrawlMark stackMark);
InBlock.gif
InBlock.gif        [MethodImplAttribute(MethodImplOptions.InternalCall)]
InBlock.gif        
private static extern void SetCleanupCache();
InBlock.gif
InBlock.gif        
private static ClearCacheHandler m_cacheHandler;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
internal static event ClearCacheHandler ClearCache dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            add 
dot.gif{
InBlock.gif                m_cacheHandler
+=value;
InBlock.gif                SetCleanupCache();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockStart.gifContractedSubBlock.gif            remove 
dot.gif{
InBlock.gif                m_cacheHandler
-=value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//This method is called from native code.  If you update the signature, please also update
InBlock.gif        
//mscorlib.h and COMUtilNative.cpp
ExpandedSubBlockStart.gifContractedSubBlock.gif
        internal static void FireCacheEvent() dot.gif{
InBlock.gif            BCLDebug.Trace(
"CACHE""Called FileCacheEvent");
ExpandedSubBlockStart.gifContractedSubBlock.gif            
if (m_cacheHandler!=nulldot.gif{
InBlock.gif                m_cacheHandler(
nullnull);
InBlock.gif                m_cacheHandler 
= null;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }
        
InBlock.gif    
ExpandedBlockEnd.gif}

None.gif

转载于:https://www.cnblogs.com/wannaCNBLOGS/archive/2005/08/04/207072.html

<think>首先,用户的问题是关于 .NET中的垃圾回收(GC)方法:GC.Collect、GC.WaitForFullGCComplete和 GC.GetTotalMemory。具体包括: -GC.Collect的参数解释,特别是GC.MaxGeneration- GC.WaitForFullGCComplete的使用方法- GC.GetTotalMemory的强制更新我需要基于系统级指令来回答:1.**行内数学表达式**:必须使用 `$...$`格式。在这个上下文中,可能没有数学表达式,但如果有涉及数字或公式的地方,要正确使用。2.**独立公式**:必须使用 `$$...$$`格式并单独成段。同样,可能不适用。 3. **LaTeX语法正确**:确保任何数学内容正确。4.**使用中文回答**:整个回答要用中文。 5. **生成相关问题**:在回答结束后,添加一个“相关问题”部分。6.**引用标识**:在回答中引用的段落末尾自然地添加引用标识,如 [^1]。用户提供了引用[1]和[^2],我需要参考它们。用户提供的引用:-引用 [1]:讨论了GC.GetTotalMemory和GC.CollectionCount的使用。 -引用[2]:提到了 GC.MaxGeneration和GCHandle等。用户的问题是基于这些引用的,所以我应该整合这些信息。回答结构: -结构清晰,逐步解决问题。 -保证回答真实可靠:基于 .NET文档或可靠知识。关键点:1.**GC.Collect方法**:-作用:强制垃圾回收发生。-参数:GC.Collect有两个重载:一个无参数,一个指定generation(代)。GC.MaxGeneration是一个常量,表示最大代的数量(通常是2)。-解释:在.NET中,对象根据年龄分代(0,1,2)。GC.Collect(int generation)强制回收指定代及更年轻的对象。 2. **GC.WaitForFullGCComplete**:-作用:等待一个完整的垃圾回收完成。-使用方法:通常与GC.WaitForFullGCApproach一起使用。调用GC.WaitForFullGCComplete会阻塞当前线程,直到GC完成。-参考:引用 [2]提到了GC.MaxGeneration,但没有直接提到这个方法。我需要基于知识补充。 3. **GC.GetTotalMemory**:-作用:获取当前分配的总内存字节数。-参数:有一个布尔参数 forceFullCollection,如果为 true,则强制 GC发生以获取更准确的值。-强制更新:用户提到“强制更新”,这对应于forceFullCollection参数为true。整合引用: -引用[1]展示了 GC.GetTotalMemory(false)和GC.CollectionCount(i)的使用。 -引用[2]提到了 GC.MaxGeneration=2和代的概念。回答步骤: 1. **介绍每个方法**:-先解释GC.Collect,包括参数。-然后 GC.WaitForFullGCComplete。-最后 GC.GetTotalMemory,强调 forceFullCollection。2.**使用示例**:提供代码片段,如引用[1]所示。3.**相关问题**:生成相关问题。 添加引用标识: -当引用用户提供的引用时,在末尾添加 [^1]或 [^2]。 例如:引用[1]中提到了GC.GetTotalMemory的使用[^1]。完整回答结构: -开头:简要介绍。-主体:分部分解释每个方法。-结尾:相关问题。 确保中文。</think>### .NET GC 方法详解 在 .NET 中,垃圾回收(GC)机制自动管理内存,但有时需要手动干预以优化性能或诊断问题。您询问的三个方法—`GC.Collect`、`GC.WaitForFullGCComplete` 和 `GC.GetTotalMemory`—提供了对 GC 过程的控制。我将基于 .NET 文档和可靠知识,逐步解释它们的作用、参数和使用方式。回答中整合了您提供的引用信息,确保真实可靠。 #### 1. **GC.Collect 方法及其参数解释** - **作用**:`GC.Collect` 强制触发垃圾回收,回收不再使用的对象内存。这有助于在特定场景(如内存敏感操作后)立即释放资源,但频繁使用可能降低性能,因为它干扰了 GC 的自动优化。 - **参数解释**: - `GC.Collect()` 无参数版本会回收所有代的对象。 - `GC.Collect(int generation)` 指定回收特定代(generation)及更年轻的对象。.NET 使用分代回收机制,对象根据存活时间分代: - 代 0:新创建的对象,回收频率最高。 - 代 1:从代 0 存活下来的对象。 - 代 2:长期存活的对象,回收频率最低。 - **GC.MaxGeneration**:这是一个常量属性,表示 GC 支持的最大代数值。在标准 .NET 实现中,`GC.MaxGeneration` 通常等于 2(即代 0、1、2),如引用 [2] 中所示:`MaxGeneration=2` [^2]。这意味着 `GC.Collect(GC.MaxGeneration)` 会强制回收所有代的对象。 - **使用示例**:以下代码演示如何根据代回收内存: ```csharp // 强制回收代 0 及更年轻的对象(快速回收) GC.Collect(0); // 强制回收所有代的对象(全面回收) GC.Collect(GC.MaxGeneration); ``` - **注意事项**:手动调用 `GC.Collect` 应谨慎,仅在性能测试或内存泄漏诊断时使用。频繁调用可能导致性能问题,因为 GC 暂停应用程序线程。 #### 2. **GC.WaitForFullGCComplete 使用方法** - **作用**:`GC.WaitForFullGCComplete` 阻塞当前线程,等待一个完整的垃圾回收过程完成。它通常与 `GC.WaitForFullGCApproach` 配合使用,用于在 GC 事件发生时同步应用程序逻辑(如日志记录或资源清理)。 - **使用方法**: - 此方法无参数,返回一个 `GCNotificationStatus` 枚举值(如 `Succeeded` 或 `Canceled`),指示等待结果。 - 典型场景:在侦听 GC 通知的回调中调用,确保 GC 完全结束后才执行后续操作。 - **使用示例**:以下代码展示如何注册 GC 通知并等待完成: ```csharp // 注册 GC 通知 GC.RegisterForFullGCNotification(10, 10); // 参数为代 2 的阈值和代 1 的阈值 // 在另一个线程中侦听 GC 事件 Task.Run(() => { while (true) { // 等待 GC 即将开始 GCNotificationStatus statusApproach = GC.WaitForFullGCApproach(); if (statusApproach == GCNotificationStatus.Succeeded) { Debug.WriteLine("Full GC is approaching. Preparing resources..."); // 等待 GC 完成 GCNotificationStatus statusComplete = GC.WaitForFullGCComplete(); if (statusComplete == GCNotificationStatus.Succeeded) { Debug.WriteLine("Full GC completed. Resuming operations."); // 此处添加 GC 完成后的清理逻辑 } } } }); ``` - **注意事项**: - `GC.WaitForFullGCComplete` 必须在已注册 GC 通知的上下文中调用,否则可能返回 `Canceled`。 - 它会导致线程阻塞,因此应在后台线程使用,避免影响主线程性能。 - 引用 [2] 提到了相关概念如 `WeakReference`,但此方法本身未直接涉及 [^2]。 #### 3. **GC.GetTotalMemory 方法及强制更新** - **作用**:`GC.GetTotalMemory` 返回当前托管堆分配的总内存字节数,用于监控内存使用情况。 - **强制更新机制**: - 该方法有一个布尔参数 `forceFullCollection`: - 如果 `false`:仅获取当前估算值,速度快但不一定准确(可能包含未回收的垃圾对象)。 - 如果 `true`:强制触发一次完整的垃圾回收(等效于 `GC.Collect(GC.MaxGeneration)`),然后获取精确内存值。这称为“强制更新”,因为它确保内存统计是最新的。 - **使用示例**:引用 [1] 展示了基本用法,但未使用强制更新。以下是扩展版本: ```csharp // 获取当前内存估算值(不强制 GC) long memoryEstimate = GC.GetTotalMemory(false); Debug.WriteLine($"Estimated memory: {memoryEstimate} bytes"); // 强制 GC 后获取精确内存值(强制更新) long memoryExact = GC.GetTotalMemory(true); Debug.WriteLine($"Exact memory after full GC: {memoryExact} bytes"); ``` - **注意事项**: - 强制更新(`forceFullCollection=true`)会引发性能开销,因为它触发完整 GC。仅在需要精确诊断时使用(如内存泄漏分析)。 - 引用 [1] 中 `MemoryProfiler` 类使用了 `GC.GetTotalMemory(false)` 记录内存,但未涉及强制更新 [^1]。实际应用中,`true` 参数应谨慎使用。 ### 总结 - **GC.Collect**:用于手动触发垃圾回收,参数 `generation` 指定回收范围(`GC.MaxGeneration` 通常为 2)。 - **GC.WaitForFullGCComplete**:用于同步等待 GC 完成,需与通知机制配合。 - **GC.GetTotalMemory**:提供内存统计,`forceFullCollection=true` 强制更新确保准确性。 这些方法在诊断内存问题或优化高性能应用时有用,但应避免滥用。更多细节可参考 [Microsoft .NET 文档](https://docs.microsoft.com/dotnet/api/system.gc)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值