[译]WebAssembly 中的 Memory

原文连接:https://fanmingfei.com/posts/...html

这是系列文章第二篇:git


WebAssembly中的内存与JavaScript中的内存有所不一样。使用WebAssembly,您能够直接访问原始字节码...这可能使人担心。可是,它的确比你想象中的要安全。浏览器

什么是 memory 对象?

当 WebAssembly 模块被实例化时,它须要一个 memory 对象。你能够建立一个新的WebAssembly.Memory并传递该对象。若是没有建立 memory 对象,在模块实例化的时候将会自动建立,而且传递给实例。安全

JS引擎建立一个ArrayBuffer(我在另外一篇文章中解释)来作这件事情。ArrayBuffer 是 JS 引用的 JavaScript 对象。JS 为你分配内存。你告诉它须要多少内存,它会建立一个对应大小的ArrayBuffer。函数

React.js requesting a new memory object and JS engine creating one

数组的索引能够视为内存地址。若是你须要增长它的内存,你可使用 grow 方法让数组变大。post

ArrayBuffer 作了两件事情,一件是作 WebAssembly 的内存,另一件是作 JavaScript 的对象。编码

  1. 它使 JS 和 WebAssembly 之间传递内容更方便。

  2. 使内存管理更安全。

JS 和 WebAssembly 之间传值

由于 ArrayBuffer 是一个 JavaScript 对象,这意味着 JavaScript 也能够获取到这个 memory 中的字节。因此经过这种方式, WebAssembly 和 JavaScript 能够共享内存,而且相互传值。

使用数组索引来访问每一个字节,而不是使用内存地址。

好比,WebAssembly 想将一个字符串写入内存。它须要将字符串转换成字节码。

WebAssembly robot putting string "Hello" through decoder ring

而后把这些字节码放进数组。

WebAssembly robot putting bytes into memory

而后将字符串所在的内存位置的第一个位置,也就是数组的某个索引,传递给 JavaScript。JavaScript 能够根据索引从 ArrayBuffer 中拿到字符串

WebAssembly robot returning index of first byte in string

如今,不少人并不知道如何在 JavaScript 中使用字节码。你须要将字节码转换为有用的内容,好比说字符串。

在一些浏览器中,你可使用TextDecoderTextEncoderAPI来处理。或者你能够在你的js文件里添加一些帮助函数。好比,Emscripten就能够帮你添加编码和解码的方法。

JS engine pulling out bytes, and React.js decoding them

因此,WebAssembly memory 最好的地方就是它是一个 JS 对象。WebAssembly 和 JavaScript 能够直接使用 memory 互相传值。

让 memory 存取更安全

另一个好处是,WebAssembly memory 只是一个 JavaScript 对象:安全。经过防止浏览器级内存泄漏并提供内存隔离,使事情变得更安全。

内存泄漏

正如我在内存管理的文章中提到的,当你管理本身的内存时,你可能会忘记清除它。这可能致使系统内存不足。

若是 WebAssembly 模块实例直接访问内存,而且若是在超出范围以前忘记清除该内存,那么浏览器可能会泄漏内存。

由于内存对象只是一个JavaScript对象,因此它自己就被垃圾回收器跟踪(尽管它的内容不会垃圾回收)。

也就是说,WebAssembly 实例被移除之后,全部的内存数组将会被回收。

Garbage collector cleaning up memory object

内存隔离

当人们听到WebAssembly让你直接访问内存时,他们可能有点紧张。他们认为,一个恶意的 WebAssembly 模块可能会进入并在内存中干坏事,这是绝对不容许的。但事实并不是如此。

ArrayBuffer 提供了边界。WebAssembly 模块能够直接管理的内存是受限制的。

Red arrows pointing to the boundaries of the memory object

它能够直接管理该数组内部的字节,但它看不到任何超出此数组范围的内容。

例如,内存中的任何其它 JS 对象,如 window 对象,WebAssembly没法访问。这对安全性很是重要。

每当 WebAssembly 中有操做内存时,引擎会进行数组限制检查,以确保该地址位于 WebAssembly 实例的内存中。

若是代码尝试访问超出范围的地址,引擎将抛出异常。这保护了其它的内存。

WebAssembly trying to store out of bounds and being rejected

因此这就是 memory 相关的内容。在下一篇文章中,咱们将看研究一些关于安全性的其它类型的 import 数据:table import

About

Lin Clark

Lin 是Mozilla Developer Relations团队的工程师。她使用 JavaScript、WebAssembly、Rust 和 Servo,也画一些漫画。

相关文章
相关标签/搜索