You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不修改源码的前提下,运行时统计类型X的对象实例数?

统计不同程序集下类型X的运行时实例总数(无需修改目标代码)

纯反射无法直接获取CLR中所有存活的对象实例,以下是几种适配不同场景的可行方案:

方案1:使用.NET诊断API(堆快照统计)

适合.NET Core/.NET 5+版本,通过获取进程堆快照实现一次性统计,无需修改目标代码,实现成本低。

实现步骤:

  1. 引用NuGet包:Microsoft.Diagnostics.NETCore.Client 和 Microsoft.Diagnostics.Runtime
  2. 编写统计代码:
using Microsoft.Diagnostics.Runtime;

public static int CountTypeXInstances()
{
    using var dataTarget = DataTarget.AttachToProcess(
        System.Diagnostics.Process.GetCurrentProcess().Id, 
        TimeSpan.FromSeconds(5), 
        AttachFlag.Passive);
    
    ClrRuntime runtime = dataTarget.ClrVersions.First().CreateRuntime();
    // 替换为X的完整命名空间+类型名
    ClrType typeX = runtime.Heap.GetTypeByName("YourNamespace.X");
    
    if (typeX == null)
        return 0;
    
    int count = 0;
    foreach (ClrObject obj in runtime.Heap.EnumerateObjects())
    {
        if (obj.Type == typeX)
            count++;
    }
    
    return count;
}

注意事项:

  • 堆快照会短暂暂停进程,适合非实时的一次性统计场景
  • 若X类型存在于多个程序集,可通过typeX.Module.AssemblyName区分筛选
  • 需确保类型的完整名称(含命名空间)准确无误

方案2:CLR探查器(实时统计)

适用于所有.NET版本(包括.NET Framework),通过编写CLR探查器拦截对象分配事件,实现实时精准统计。

核心逻辑:

实现ICorProfilerCallback接口的ObjectAllocated方法,每次对象分配时检查类型是否为X,匹配则累加计数。同时可通过弱引用跟踪实例存活状态,避免统计已回收对象。

关键要点:

  • 需用C++编写探查器并注册到CLR运行时
  • 可拦截所有程序集中的X类型实例分配事件
  • 实现复杂度较高,需熟悉CLR Profiling API底层机制

方案3:动态代码注入(实时统计)

利用AOP框架动态注入构造函数钩子,跟踪X类型实例的创建,适合允许动态修改运行时代码的场景。

实现示例(基于Harmony库):

  1. 引用NuGet包:Lib.Harmony
  2. 编写跟踪代码:
using HarmonyLib;
using System.Collections.Generic;
using System.Reflection;

public static class InstanceTracker
{
    private static readonly List<WeakReference> _xInstances = new List<WeakReference>();
    
    public static int GetXInstanceCount()
    {
        lock (_xInstances)
        {
            // 清理已被GC回收的实例引用
            _xInstances.RemoveAll(r => !r.IsAlive);
            return _xInstances.Count;
        }
    }
    
    public static void HookTypeXConstructors()
    {
        var harmony = new Harmony("XInstanceTracker");
        
        // 遍历所有程序集,查找类型X
        var typeXList = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(asm => asm.GetTypes())
            .Where(t => t.Name == "X") // 可替换为FullName提升精准度
            .ToList();
        
        foreach (var typeX in typeXList)
        {
            // Hook所有构造函数(含私有构造)
            var ctors = typeX.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (var ctor in ctors)
            {
                harmony.Patch(ctor, postfix: new HarmonyMethod(typeof(InstanceTracker).GetMethod("PostfixCtor")));
            }
        }
    }
    
    private static void PostfixCtor(object __instance)
    {
        lock (_xInstances)
        {
            _xInstances.Add(new WeakReference(__instance));
        }
    }
}

使用方式:

程序启动时调用InstanceTracker.HookTypeXConstructors()完成钩子注入,后续随时调用InstanceTracker.GetXInstanceCount()获取当前存活实例数。

注意事项:

  • 动态注入需要足够权限,沙箱等受限环境可能无法运行
  • 需覆盖所有程序集中的X类型,确保无遗漏构造函数
  • 用WeakReference存储实例,避免内存泄漏导致实例无法被GC回收

内容的提问来源于stack exchange,提问作者DuckQueen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:47:22