2

在我的顶部,我bootstrap.js定义了一堆lazyGetters,而不是 JSM:

const myServices = {};
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyGetter(myServices, 'sss', function(){ return Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService) });

我听说你必须unload导入模块。但是你为lazyGetters 创建的“模块”呢?我将如何卸载那些?我会做一个delete myServices吗?

如果我执行一个全局变量deletemyServices这是否意味着我应该在卸载时删除所有全局变量?

我在这里读到:忘记在无需重启的附加组件中卸载 JavaScript 模块

忘记在无需重启的附加组件中卸载 JavaScript 模块

泄漏的另一个常见原因是忘记在引导加载项中卸载 JavaScript 代码模块。通过查看 about:compartments 或 about:memory 无法检测到这些泄漏,因为此类模块位于主系统隔间内。

此外,当您的插件更新并重新启用时,将使用仍加载的先前模块版本,这可能会完全破坏您的插件。

以下示例显示了如何再次卸载模块 (bootstrap.js):

Components.utils.import("resource://gre/modules/Services.jsm");

function startup(data, reason) {
  // This assumes your add-on did register some chrome
  Components.utils.import("chrome://myaddon/content/mymodule.jsm");
}

function shutdown(data, reason) {
  if (reason != APP_SHUTDOWN) {
    // No need to do regular clean up when the application is closed
    // unless you need to break circular references that might negatively
    // impact the shutdown process.
    return;
  }

  // Your add-on needs to unload all modules it ships and imported!
  Components.utils.unload("chrome://myaddon/content/mymodule.jsm");
}

注意:不属于您的附加组件的模块(例如 Services.jsm)不应由您的附加组件卸载,因为这可能会导致错误和/或性能下降,并且实际上会增加内存使用量。

4

1 回答 1

2

您提供的代码没有导入模块,而是定义了一个服务获取器,所以没问题。

(旁白:还有一个XPCOMUtils.defineLazyServiceGetter帮手……)

但是,如果您执行以下操作:

XPCOMUtils.defineLazyGetter(myServices, 'SomeSymbol', function() {
   return Cu.import("chrome://myaddon/content/mymodule.jsm", {}).SomeSymbol;
});

那么你当然需要Cu.unload()再次访问该模块。最好通过注册模块以在加载后立即卸载来完成(IMO),例如:

XPCOMUtils.defineLazyGetter(myServices, 'SomeSymbol', function() {
   let rv = Cu.import("chrome://myaddon/content/mymodule.jsm", {}).SomeSymbol;
   unload(function() {
     Cu.unload("chrome://myaddon/content/mymodule.jsm");
   });
   return rv;
});

其他人只是主动卸载所有可能已导入或未导入的模块。这很好,因为Cu.unload()没有导入的模块什么都不做。

PS:将某些东西粘贴到另一个模块中时,您仍然会遇到麻烦,例如。

XPCOMUtils.defineLazyServiceGetter(Services /* other module */,
                                   'sss',
                                   '@mozilla.org/content/style-sheet-service;1',
                                   'nsIStyleSheetService');

在此示例XPCOMUtils.jsm中,可能仍会引用从您的代码中作为参数传递的字符串,从而泄漏您的代码。(此外,将东西粘贴到不属于您自己的模块中是相当粗鲁的,并且可能会与其他执行相同操作的附加组件产生冲突。)

于 2014-07-22T11:41:11.547 回答