2

我正在尝试创建一个动态组件。是 plunker 中的示例。http://embed.plnkr.co/EVFglgkp24hkRkpxrEGe/ 一切正常,但存在内存泄漏。

是 github 票https://github.com/angular/angular/issues/19997

动态创建的组件正在被销毁,但创建动态组件的组件并没有被销毁。换句话说,编译动态组件的组件没有被破坏

在上面的示例中,如果我们在“主页”和“动态页面”之间来回导航并在 chrome 中拍摄内存快照,您可以看到假设被销毁的组件仍然存在,如下图所示。

在此处输入图像描述

出于测试目的,我什至尝试评论以下行,但问题仍然存在。

      let injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
      let ngMdlRef = ngMdlFac.create(injector);
      let cmpFactory = ngMdlRef.componentFactoryResolver.resolveComponentFactory(DynamicHtmlComponent);
      this.cmpRef = this.vcRef.createComponent(cmpFactory);

我打电话的那一刻

this.compiler.compileModuleAsync

创建者组件根本没有被破坏。在那之前没有问题。

你能请人帮忙吗?先感谢您。

4

1 回答 1

5

您是对的,内存泄漏的问题是由手动模块编译和实例化引起的。如果您查看 的保持器,MyCreatorComponent您可以看到该函数DynamicHtmlComponent并通过上下文DynamicModule保存对父函数的引用。MyCreatorComponent

在此处输入图像描述

这些是距离 GC 根最短的对象,因此它们很可能是造成内存泄漏的对象。问题是为什么它们没有被删除?答案是 Angular 会大量缓存它创建的所有内容,并且在您的情况下也会发生这种情况。通过快速浏览,我已经确定了至少两个保留引用的缓存。

第一的

export class JitCompiler {
  private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();

当您调用this.compiler.compileModuleAsync(DynamicModule)Angular 时,会将CompiledTemplate密钥添加DynamicHtmlComponent到此缓存中并且永远不会清除它。

第二

const _tokenKeyCache = new Map<any, string>();

当你调用var ngMdlRef = ngMdlFac.create(...)Angular 时,它会添加DynamicHtmlComponentFactory到这个缓存中并且永远不会删除它。

请注意,只要没有对对象的显式调用,这些缓存就Maps不会被保留。WeakMaps.delete()

于 2017-10-28T17:47:10.440 回答