必须用 postmessage(arraybuffer, [arraybuffer]) 显式移交 arraybuffer 所有权;传输几 mb 以上数据时,不 transfer 会导致深拷贝耗尽内存、卡死主线程,如上传 200mb 视频、处理 4k 帧、解析 gb 级点云。

关键就一条:用 postMessage(arrayBuffer, [arrayBuffer]) 显式移交所有权,移交后原线程立即失效,不能读写、不能 JSON.stringify、不能留着当变量用。
什么时候必须用 transfer?
传输大于几 MB 的 ArrayBuffer 时,结构化克隆的深拷贝会吃光内存、卡死主线程。比如上传 200MB 视频、处理 4K 图像帧、解析 GB 级点云数据——这些场景不 transfer,性能直接崩盘。
- 典型触发点:
file.arrayBuffer()、fetch().arrayBuffer()、ctx.getImageData().data.buffer返回的 buffer - 小数据(
- 如果主线程后续还要读这个 buffer,就不能 transfer,只能接受拷贝代价
怎么写才不会报 detached 错误?
移交是单向、不可逆、即时生效的。常见错误不是语法错,而是逻辑残留。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 发送后立刻检查:
if (buffer.byteLength === 0) console.log('已移交') - 别在 postMessage 后继续用
new Uint8Array(buffer)—— 这会直接抛TypeError: ArrayBuffer is detached - 避免视图泄漏:移交前确保所有基于该 buffer 的 TypedArray / DataView 实例已丢弃引用
- 不要对已移交的 buffer 调用
JSON.stringify,它会静默失败,不报错但返回空对象
Worker 接收端要注意什么?
接收方拿到的是裸 buffer,没附带长度或类型信息,得靠协议约定或额外字段说明。
- 正确写法:
const view = new Uint8Array(e.data)——e.data就是移交来的 ArrayBuffer - 别传 TypedArray 实例(如
Uint8Array)进 transfer list,只传.buffer - 如果需多次复用,可在 Worker 内预分配大 buffer,再用
subarray()切片视图,避免反复创建 - 不能跨多个 Worker 转发:从 A 发给 B 后,B 想发给 C,必须再次显式写
workerC.postMessage(buf, [buf])
还有哪些容易忽略的边界情况?
Blob 不能直接 transfer;SharedArrayBuffer 需跨域隔离且要 Atomics 同步;JSVM 等嵌入式环境零拷贝不保证。
- Blob 要先转 ArrayBuffer:
await blob.arrayBuffer(),再 transfer - SharedArrayBuffer 不等于零拷贝“共享”,它允许多线程并发读写,但需手动同步,且不适用于普通 Web Worker(仅支持主线程 + SharedWorker 或 Worker + Worker)
- 在 JSVM 或某些 WebView 中,
copied输出参数可能为 true,意味着外部内存被复制了,此时调用方可立即释放原始内存 - transfer list 必须精确匹配:传
[buf],但实际发的是buf.slice(0),那移交失败,仍走拷贝
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










