Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net Microsoft Unity-DerivedTypeConstructorSelectorPolicy内存泄漏_.net_Memory Leaks_Unity Container - Fatal编程技术网

.net Microsoft Unity-DerivedTypeConstructorSelectorPolicy内存泄漏

.net Microsoft Unity-DerivedTypeConstructorSelectorPolicy内存泄漏,.net,memory-leaks,unity-container,.net,Memory Leaks,Unity Container,因此,我们遇到了一个问题,即容器在应用程序期间一直保留DerivedTypeConstructorSelectorPolicy的实例。如果不是因为TypeInterceptionStrategy中的以下两行代码将旧策略包装成一个新策略这一事实,那么这就不会那么糟糕了,新策略现在保留了两个实例(或者更多,对于一个被拦截的类,每次调用解析都会使问题复杂化)。运行.NET内存分析器时可以看到这一点 IConstructorSelectorPolicy originalConstructorSelect

因此,我们遇到了一个问题,即容器在应用程序期间一直保留DerivedTypeConstructorSelectorPolicy的实例。如果不是因为TypeInterceptionStrategy中的以下两行代码将旧策略包装成一个新策略这一事实,那么这就不会那么糟糕了,新策略现在保留了两个实例(或者更多,对于一个被拦截的类,每次调用解析都会使问题复杂化)。运行.NET内存分析器时可以看到这一点

IConstructorSelectorPolicy originalConstructorSelectorPolicy = PolicyListExtensions.Get<IConstructorSelectorPolicy>(context.Policies, (object) context.BuildKey, out containingPolicyList);
PolicyListExtensions.Set<IConstructorSelectorPolicy>(containingPolicyList, (IConstructorSelectorPolicy) new TypeInterceptionStrategy.DerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), (object) context.BuildKey);
IConstructorSelectorPolicy originalConstructorSelectorPolicy=PolicyListExtensions.Get(context.Policies,(object)context.BuildKey,out containingPolicyList);
PolicyListExtensions.Set(包含PolicyList,(IConstructorSelectorPolicy)新类型拦截策略。派生类型构造函数SelectorPolicy(proxyType,originalConstructorSelectorPolicy),(对象)上下文.BuildKey);
当有很多类被截获时,这会导致Gen 2集合的抖动,然后在内存中出现GC无法回收的漏洞,尤其是在复制策略以确保线程安全的情况下。一旦您在策略列表中有足够数量的项,它将被移动到LOH,这使得打击更加严重

我应该提醒大家,我们的应用程序是在IIS经典而非集成管道中运行的,并且是在32位模式下运行的,我知道这是双重打击。在64位模式下,有了更多的可寻址空间,情况就不会那么糟了。但是,我们仍然被IIS提供给我们的虚拟内存所困扰,这很快就会发生,因为GC在VM映射中找不到足够的空间来分配额外的内存,请求开始消亡

该文件只有3个版本,原始版本看起来似乎没有这个问题。有没有其他人遇到过这个问题,或者我遗漏了一些可能可以解释这种行为的东西

pastebin上发布了一个非常简单的程序链接,说明了这一点:

使用.NET内存探查器(或您选择的探查器)并观察DerivedTypeConstructorSelectorPolicy,您可以观察它在每次迭代中的增长,随着它的增长,您可以检查并看到originalConstructorSelectorPolicy在长链中不断引用旧实例


例如,我们拦截了多少个类,大约有1300个注册。

与此同时,我找到了一个解决方案。这是一个简单的修复,但它要求您覆盖拦截并键入拦截策略。修复方法是一行程序,只需检查策略列表中出现的类型

这是TypeInterceptionStrategy中的代码:

if (originalConstructorSelectorPolicy is DefaultUnityConstructorSelectorPolicy)
{
    containingPolicyList.Set<IConstructorSelectorPolicy>(new CustomDerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), context.BuildKey);
}
if(原始构造函数SelectorPolicy为DefaultUnityConstructorSelectorPolicy)
{
containingPolicyList.Set(新的CustomDerivedTypeConstructorSelectorPolicy(proxyType,originalConstructorSelectorPolicy),context.BuildKey);
}
当然,为了改变这一点,您必须复制TypeInterceptionStrategy,并执行与该修复相同的操作,它不能简单地通过覆盖预构建方法来修复

我在这里粘贴整个修复程序,以防其他人遇到问题

public class CustomTypeInterceptionStrategy : BuilderStrategy
{
    public override void PreBuildUp(IBuilderContext context)
    {
        Guard.ArgumentNotNull(context, "context");

        if (context.Existing != null)
        {
            return;
        }

        Type type = context.BuildKey.Type;
        ITypeInterceptionPolicy typePolicy = FindInterceptionPolicy<ITypeInterceptionPolicy>(context);

        if (typePolicy == null)
        {
            return;
        }

        ITypeInterceptor interceptor = typePolicy.GetInterceptor(context);

        if (!interceptor.CanIntercept(type))
        {
            return;
        }

        IInterceptionBehaviorsPolicy behaviorPolicy = FindInterceptionPolicy<IInterceptionBehaviorsPolicy>(context);

        IEnumerable<IInterceptionBehavior> interceptionBehaviors = behaviorPolicy == null
                                                                       ? Enumerable.Empty<IInterceptionBehavior>()
                                                                       : behaviorPolicy.GetEffectiveBehaviors(context, interceptor, type, type).Where(ib => ib.WillExecute);

        IAdditionalInterfacesPolicy interceptionPolicy3 = FindInterceptionPolicy<IAdditionalInterfacesPolicy>(context);
        IEnumerable<Type> additionalInterfaces1 = interceptionPolicy3 != null ? interceptionPolicy3.AdditionalInterfaces : Type.EmptyTypes;
        context.Policies.Set(new CustomEffectiveInterceptionBehaviorsPolicy() { Behaviors = interceptionBehaviors }, context.BuildKey);

        Type[] additionalInterfaces2 = Intercept.GetAllAdditionalInterfaces(interceptionBehaviors, additionalInterfaces1);
        Type proxyType = interceptor.CreateProxyType(type, additionalInterfaces2);

        IPolicyList containingPolicyList;
        IConstructorSelectorPolicy originalConstructorSelectorPolicy = context.Policies.Get<IConstructorSelectorPolicy>(context.BuildKey, out containingPolicyList);

        if (originalConstructorSelectorPolicy is DefaultUnityConstructorSelectorPolicy)
        {
            containingPolicyList.Set<IConstructorSelectorPolicy>(new CustomDerivedTypeConstructorSelectorPolicy(proxyType, originalConstructorSelectorPolicy), context.BuildKey);
        }
    }

    public override void PostBuildUp(IBuilderContext context)
    {
        Guard.ArgumentNotNull(context, "context");

        IInterceptingProxy interceptingProxy = context.Existing as IInterceptingProxy;

        if (interceptingProxy == null)
        {
            return;
        }

        CustomEffectiveInterceptionBehaviorsPolicy interceptionBehaviorsPolicy = context.Policies.Get<CustomEffectiveInterceptionBehaviorsPolicy>(context.BuildKey, true);

        if (interceptionBehaviorsPolicy == null)
        {
            return;
        }

        foreach (IInterceptionBehavior interceptor in interceptionBehaviorsPolicy.Behaviors)
        {
            interceptingProxy.AddInterceptionBehavior(interceptor);
        }
    }

    private static TPolicy FindInterceptionPolicy<TPolicy>(IBuilderContext context) where TPolicy : class, IBuilderPolicy
    {
        TPolicy policy = context.Policies.Get<TPolicy>(context.BuildKey, false);

        if (policy != null)
        {
            return policy;
        }

        return context.Policies.Get<TPolicy>(context.BuildKey.Type, false);
    }

    private class CustomEffectiveInterceptionBehaviorsPolicy : IBuilderPolicy
    {
        public CustomEffectiveInterceptionBehaviorsPolicy()
        {
            this.Behaviors = new List<IInterceptionBehavior>();
        }

        public IEnumerable<IInterceptionBehavior> Behaviors { get; set; }
    }

    private class CustomDerivedTypeConstructorSelectorPolicy : IConstructorSelectorPolicy
    {
        private readonly Type interceptingType;
        private readonly IConstructorSelectorPolicy originalConstructorSelectorPolicy;

        public CustomDerivedTypeConstructorSelectorPolicy(Type interceptingType, IConstructorSelectorPolicy originalConstructorSelectorPolicy)
        {
            this.interceptingType = interceptingType;
            this.originalConstructorSelectorPolicy = originalConstructorSelectorPolicy;
        }

        public SelectedConstructor SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination)
        {
            return FindNewConstructor(this.originalConstructorSelectorPolicy.SelectConstructor(context, resolverPolicyDestination), this.interceptingType);
        }

        private static SelectedConstructor FindNewConstructor(SelectedConstructor originalConstructor, Type interceptingType)
        {
            ParameterInfo[] parameters = originalConstructor.Constructor.GetParameters();
            SelectedConstructor selectedConstructor = new SelectedConstructor(interceptingType.GetConstructor(parameters.Select(pi => pi.ParameterType).ToArray()));

            foreach (string newKey in originalConstructor.GetParameterKeys())
            {
                selectedConstructor.AddParameterKey(newKey);
            }

            return selectedConstructor;
        }
    }
}

public class CustomInterception : Interception
{
    protected override void Initialize()
    {
        this.Context.Strategies.AddNew<InstanceInterceptionStrategy>(UnityBuildStage.Setup);
        this.Context.Strategies.AddNew<CustomTypeInterceptionStrategy>(UnityBuildStage.PreCreation);
        this.Context.Container.RegisterInstance(typeof(AttributeDrivenPolicy).AssemblyQualifiedName, (InjectionPolicy)new AttributeDrivenPolicy());
    }
}
公共类CustomTypeInterceptionStrategy:BuilderStrategy
{
公共覆盖无效预构建(IBuilderContext上下文)
{
ArgumentNotNull(上下文,“上下文”);
if(context.Existing!=null)
{
返回;
}
Type Type=context.BuildKey.Type;
ITypeInterceptionPolicyTypePolicy=FindInterceptionPolicy(上下文);
if(typePolicy==null)
{
返回;
}
ITypeInterceptor interceptor=typePolicy.GetInterceptor(上下文);
if(!interceptor.CanIntercept(类型))
{
返回;
}
IIInterceptionBehaviorPolicy behaviorPolicy=FindInterceptionPolicy(上下文);
IEnumerable拦截行为=行为策略==null
?可枚举。空()
:behaviorPolicy.GetEffectiveBehaviors(上下文、拦截器、类型、类型)。其中(ib=>ib.WillExecute);
IAdditionalInterfacesPolicy拦截策略3=FindInterceptionPolicy(上下文);
IEnumerable additionalInterfaces1=interceptionPolicy3!=null?interceptionPolicy3.AdditionalInterfaces:Type.EmptyTypes;
context.Policies.Set(新的CustomEffectiveInterceptionBehaviorsPolicy(){Behaviors=interceptionBehaviors},context.BuildKey);
类型[]additionalInterfaces2=Intercept.GetAllAdditionalInterfaces(interceptionBehaviors,additionalInterfaces1);
Type proxyType=拦截器.CreateProxyType(Type,additionalInterfaces2);
包含保单列表的IPolicyList;
IConstructorSelectorPolicy originalConstructorSelectorPolicy=context.Policies.Get(context.BuildKey,out containingPolicyList);
如果(原始构造函数SelectorPolicy为DefaultUnityConstructorSelectorPolicy)
{
containingPolicyList.Set(新的CustomDerivedTypeConstructorSelectorPolicy(proxyType,originalConstructorSelectorPolicy),context.BuildKey);
}
}
公共覆盖无效后期构建(IBuilderContext上下文)
{
ArgumentNotNull(上下文,“上下文”);
IIInterceptingProxy interceptingProxy=上下文。作为IIInterceptingProxy存在;
if(拦截代理==null)
{
返回;
}
CustomEffectiveInterceptionBehaviorPolicy InterceptionBehaviorPolicy=context.Policies.Get(context.BuildKey,true);
if(侦听行为策略==null)
{
返回;
}
foreach(interceptionBehaviorsPolicy.Behaviors中的IIInterceptionBehavior拦截器)
{
InterceptionProxy.AddInterceptionBehavior(拦截器);
}
}
私人静电