Утечка памяти объектов ServerIdentity, сгенерированных прокси AppDomain? - PullRequest
0 голосов
/ 13 сентября 2018

Задача
TLDR; Я наблюдаю постоянную утечку ServerIdentity объектов для каждого прозрачного прокси-объекта, который я создаю.

Я создаю домены приложений в качестве механизма для песочницы для выполнения некоторых сторонних кодов и использую MarshalByRefObject и appDomain.CreateInstanceAndUnwrap() для генерации прозрачного прокси для выполнения моего кода. Однако каждый экземпляр, который я маршал, также создает соответствующий ServerIdentity, который, очевидно, поддерживается внутренним статическим классом.

Что я пробовал

  1. Выгрузка AppDomain через AppDomain.Unload(appdomain) отключает и очищает экземпляр AppDomain, но объекты ServerIdentity остаются и накапливаются.
  2. При вызове RemotingServies.Disconnect(marshalbyrefobject) выдается исключение, так как оно, очевидно, не для обработки прозрачных прокси, поскольку выдает эту ошибку: System.Runtime.Remoting.RemotingException: 'Cannot call disconnect on a proxy.'

Самым близким, к которому я пришел, чтобы найти ответ на этот вопрос, был пост в блоге , описывающий очень похожую проблему. Однако в их коде должен быть дополнительный контекст, который мне не хватает.

dotMemory Скриншоты

Количество новых объектов увеличивается с каждым запросом, мусор не собирается enter image description here

Пути хранения ключей экземпляра ServerIdentity enter image description here

Редактировать 1
Итак, я обнаружил, что вызывало исключение, упомянутое в пуле номер 2. По сути, вы не можете позвонить RemotingServices.Disconnect(proxyInstance) из основного AppDomain. Это должно быть сделано на реальном MarshalByRefObject объекте экземпляра, созданном во вторичном AppDomain. По сути, я создал свою собственную абстрактную реализацию MarshalByRefObject примерно так. Я подтвердил, что Disconnect() вызывается для каждого экземпляра с маршалингом.

public abstract class SandboxedInstance : MarshalByRefObject
{
    public sealed override object InitializeLifetimeService()
    {
        // This override implementation ensures the lifetime of this object until Dispose() is called.
        return null;
    }

    /// <summary>
    /// Method called internally when containing Sandbox is disposed, automatically disposing this object.
    /// </summary>
    internal void Disconnect()
    {
        RemotingServices.Disconnect(this);
    }
}

Однако это не решило мою проблему. Объекты ServerIdentity, кажется, все еще существуют, несмотря на то, что RemotingServies.Disconnect(marshalbyrefobject) успешно вызывается. Есть ли кто-нибудь, кто понимает, что происходит? Я могу найти очень мало документации по этому вопросу.

Редактировать 2
Есть ли кто-нибудь, кто может подтвердить эту теорию? Я читал упоминания о том, что некоторые удаленные объекты живут за пределами Disconnect(), но в конечном итоге очищаются. Основываясь на этой теории, я запустил dotMemory и наблюдал, очищались ли объекты ServerIdentity с течением времени, особенно те, которые были сохранены с помощью Lease. Это на самом деле, похоже, так. Может ли кто-нибудь со знанием этого вопроса подтвердить это?

...