大量使用 `vm.runInContext` 是否存在风险?
发布于 8 年前 作者 jiyinyiyong 4860 次浏览 来自 问答

要用到 vm 去跑很多代码, 而且会是长久存在于内存当中的实例, 并且随着服务运行可能还要缓慢增加 vm 的实例数量. 这种情况下是否会可能会由于 vm 什么问题影响性能甚至破坏服务的稳定性呢?

4 回复

你调用 vm.runInContext时,第二个参数必须传入contextifiedSandbox 所以肯定要在调用前做一个createContext的操作,比如:

var sandbox = { foo: 'bar' };
var context = vm.createContext(sandbox);
result = vm.runInContext(
'baz = foo; this.typeofProcess = typeof process; typeof Object;',
context
);

但是这里有一个比较危险的地方:createContext函数 这个函数调用了binding层的c++的一些代码,具体实现在node_contexttify.cc中 它会检测你每次传入的sandbox是否有_contextifyHidden属性,如果没有,调用ContextifyContext类给你new一个 但是偏偏这个类是很危险的,因为这个类定义了三个Persistent类型而不是Local类型的Handle:

Persistent<Object> sandbox_;
Persistent<Context> context_;
Persistent<Object> proxy_global_;

Persistent类型的handle,不受HandleScope的管理,GC无法回收。(除非使用MakeWeak弱化其引用) 这样大量的vm.createContext(js对象)被执行的话,就会造成内存泄漏

所以我觉得,只要把每一个sandbox(自己定义的js对象)写到类似全局的地方,而不是每个用户请求都重新创建一个sandbox对象的话,大量使用vm.runInContext应该也没有问题吧

@hyj1991 虽然这么说, 开始 sandbox 既然是 context 要用到的数据, 我就不好写在全局了, 还只能每次都写一个.

@jiyinyiyong 其实蛮好奇,什么样的场景会用到vm模块,哈哈

回到顶部