我正在开发一个 GWT 项目,我们偶尔使用 JSNI 来调用 native JavaScript 代码。性能瓶颈似乎是 Java 代码和 JavaScript 代码之间来回传递值。具体来说,无法将 byte[] 从 Java 端传递到 JS 代码,反之亦然 - 只能传递 int、byte、String 等,但不能传递 byte[]。这意味着我们必须在调用之前将数组转换为字符串,然后再转换回字节数组表示形式(byte[] 或 UInt8Array)。这似乎没有必要,因为 GWT 的 byte[] 必须具有某种 native JavaScript 表示形式。有谁知道GWT如何表示字节数组?更改 GWT 编译器以允许我们直接访问数组可能是一个选择。
最佳答案
几乎所有数字类型,包括 byte
,都表示为 JavaScript 数字(盒装类型和 long
除外)。编译器根据需要插入范围检查或“溢出”,以正确模拟预期的 Java 行为。
从 GWT 2.6.x(和当前的 GWT 主干)开始,任何原始数字数组在编译时都被实现为 JavaScript 数组。但是,在开发模式下运行时,将使用 native Java 数组,因此您无法编写仅将 Java 数组传递给 JavaScript 的 JSNI 代码,并期望其正常运行。请参阅http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#sharing :
Java array
opaque value that can only be passed back into Java code
即使不考虑开发模式,也要小心地将 Java 数组视为 JavaScript 数组 - 任何 future 发出类型化数组(正如您在问题中提到的)的编译器优化都可能会意外地破坏您的代码。
也就是说,有多种方法可以在 Gwt/Java 代码中创建 JavaScript 数组和 TypedArray,以便您可以从 JavaScript 使用它们。使用 JsArrayNumber
类型来保存 double 对象(回想一下,JS“数字”实际上是 Java double
),或者使用 com.google.gwt.typedarrays.shared .Uint8Array
类和 typedarrays 包的其余部分用于处理 Java 中的类型化数组。
就更改编译器而言,我去年年底提交了一个补丁( https://gwt-review.googlesource.com/4260 ),试图添加此功能。有两个主要因素阻碍了这个想法的实现:
- 首先,也是最重要的,数组编译发生了其他变化,在一个月左右的时间里多次破坏了我的补丁。这些更改改进了一般对象数组,因此是有益的,而且我认为我的补丁最终没有理由不能工作。然而...
- 该补丁将所有原始数组(除了
long
,因为JS中没有64位int类型数组)更改为基于ArrayBuffer
。有点矛盾的是,这在许多情况下都会导致性能下降,因为现在任何小数组都必须分配为类型化数组,并且当时在大多数/所有浏览器中这比实际创建典型的 JS 数组要慢目的。已经讨论了几种处理这个问题的想法 - 全局打开/关闭此功能的标志、声明实例将是类型化数组的注释、用于创建原始 Java 的特殊TypedJavaArrays
工厂类由 JS TypedArrays 支持的数组(因此任何性能问题都取决于用户)等。
如果时间允许,我仍在追求这一目标,并且不能确定它是否会成为 GWT 2.7 或更高版本 - 我们不想因为某些特殊情况而减慢所有 GWT 代码的速度无论如何都可以引用 typedarrays
包。
关于arrays - byte[] 的 GWT 内部表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24720940/