写点什么

GE Energy 利用 InvokeDynamic 指令将 Magik 移向 JVM

  • 2012-12-25
  • 本文字数:2740 字

    阅读完需:约 9 分钟

今年 7 月,GE 能源管理业务(GE Energy Management)从 GE 能源集团分离出来。同月,其数字能源部门(Digital Energy)透露,他们正在将Magik(一种受Smalltalk 启发而设计的编程语言)从其专有的虚拟机MagikSF 移植向JVM。

Magik 是一种动态类型的面向对象语言,支持多重继承和多态。它最初出现于 1990 年,比 Java 还要早。Magik 已用于 GE 能源集团的 Smallworld 技术平台,而且该语言就是为实现面向企业设施(如配电)和电信的复杂应用而设计的。比如在电信领域,GE 能源管理业务有一款名为 Physical Network Inventory 的产品,支持电信公司规划和管理其铜线、光纤和电缆的电信网络。在企业设施方面,其产品 Electric Office 为配电公司提供了类似功能。

Magik 看起来非常像 Ruby。下面是一个简单的“hello world”例子程序:

复制代码
Magik> _for i _over 1.upto(3)
_loop
write("Hello world ", i)
_endloop

在 Ruby 中写法如下:

复制代码
1. upto(3) do |i|
puts("Hello world #{i}")
end

这两段代码的输出相同,如下:

复制代码
Hello world 1
Hello world 2
Hello world 3

虽然移植工作今年 7 月份才向外界透露,但 GE 能源集团的团队在一年之前——也就是 2011 年 7 月——就开始了概念验证工作,有一个小团队在工作中使用了 Java 7 的早期发布版本。 团队主管、架构师 George Marrows 向 InfoQ 说到,

这非常成功,从那时起我们就为产品发布版本而努力了。我们编写了 Magik 语言的解析器、编译器和运行时,集成了我们的大多数 C 库,并且使用 Java2D 编写了一个全新的图形子系统,所有新设计的组件都与现有系统高度兼容。

移植尚不彻底,不过移植版本已经能够运行完整的应用程序。最关键的是,考虑到 GE 能源集团的合作伙伴与客户所编写的数百万行 Magik 代码,移植版本的目标是完全兼容 MagikSF 版本,开发者只需要简单地在 JVM 移植版本上重新编译 Magik 源代码。Marrows 对我们说,“我们确信,我们的语言实现与 MagikSF 非常非常接近,我们的库支持也做得非常好,而且随着运行的 Magik 代码越来越多以及不断修复不兼容的地方,改进也在持续进行。”

正如你所预料的那样,考虑到 Magik 的动态类型系统,移植版本大量使用了 Java 7 的 invokedynamic 字节码指令。Marrows 说到,

我们大量使用了 invokedynamic,不仅是在明显的方法分派(method dispatch)中,在将复杂字面量绑定到其使用位置以及解析全局变量时也有所应用。Duncan MacGregor 在团队中负责这项工作——使用 invokedynamic,他一度发现几乎每周都有性能改进。

invokeDynamic 和 java.lang.invoke 的使用体验非常好。我们可以将其看做 JVM JIT 编译器方法内联功能的一个 API,就这一点而言,它非常出色。我们惊喜地看到,自从去年 Java 7 的第一个版本发布以来,几乎每次更新都能带来一些性能改进;而且看起来我们还可以从 Java 8 的“lambda form”工作中继续获得改进。

从技术角度看,JVM 的很多功能 MagikSF 是不支持的,比如

  • MagikSF 是解释型的,而 JVM 支持 JIT 编译。
  • MagikSF 使用的是绿色线程,而 JVM 使用原生线程。
  • MagikSF 只支持 32 位,而 JVM 也支持 64 位。
  • MagikSF 有自己的垃圾收集器,其垃圾收集器是分代的,但并非并发垃圾收集器;而在 Hotspot 虚拟机中,Java 支持多种垃圾收集器,大多是并发收集器。

当然,像 Oracle 和 IBM 等大型软件厂商所贡献的大量资源和专家经验也让 JVM 获益良多。

Marrows 的团队看到的性能改进结果令人印象深刻:在他们运行的大多数基准测试中,Java 移植版本的速度已经有所超越,有些情况下性能改进高达 30 倍。就像 Marrows 所指出的那样,随着时间的推移,invokeDynamic 和 JVM 的性能不断改进,他们的项目也相应获益,诸如在 Java 7 update 9 上要比在 Java 7 update 2 上执行得更好。更重要的是,作为 Java 8 Lambda 项目的一部分,Oracle 重新设计了 invokeDynamic;而且这一版本正在被向后移植到 Java 7 中(按照计划,该特性将包含在即将发布的 update 12 中)。尽管 Marrows 告诉我们,有些代码实例表明,相对于 update 9,在 update 12 上运行当前测试构建时性能有些劣化,但是在很多情况下新版本会快得多;这点他们会与 Oracle 的团队讨论。到目前为止,Marrows 的团队从 Oracle,特别是 JSR 292 专家组的 Rémi Forax 那里得到了极大的支持,Rémi Forax “帮助我们开始使用 JSR 292,而且在 MLVM(multi-language virtual machine)邮件列表中,他是一位不知疲倦的贡献者”。

虽然最初没有相应计划,但团队现在还是通过混用 JNI 和 Java 2D 的方式移植了图形系统——“将 JNI 与 C 库继承,可以访问我们的数据库并执行优化的几何与其他计算。Java 2D 渲染贴图和 UI。”

该团队最终实现的从 Java 到 Magik 的内置的互操作还相当不错,Java 2D 所支持的图形系统中大量使用了这一特性。比如:

复制代码
def_slotted_exemplar(
:line_style,
{ { :colour, colour } },
{ :simple_style_mixin},
{:|com.gesmallworld.magik.commons.drawingsurface.LineStyle|})
$
_private _method line_style.|getColour|()
>> .colour
_endmethod

|getColour|中的竖线用于保留 Java 代码里的大小写,因为 Magik 是不区分大小写的。

而从 Magik 到 Java 的互操作就不是那么方便了,需要开发者编写包装代码。

复制代码
public class Char16Vector {
@MagikInitialiser
public static void exposeThisClass() {
//Expose an instance of this class to Magik
}
@MagikMethod(name="nth()")
public Char16Vector nth( Integer index ) {
return new Char16Vector(value.substring(index-1, index));
}
}

Nashorn 是 Oracle 的新 JavaScript 实现。利用 Dynalink 库,它能够更清晰地实现该功能。Jim Laskey 在其博客上提供了一个很好的例子,通过 Twitter4J 库,使用 Nashorn 与 Twitter 交互,可以很好地实现上述功能。Marrows 告诉我们,Dynalink 就是他和团队想要看到的东西。

除了能够使用 Java 虚拟机之外,该团队发现跑在 Java 平台上还有其他的优点。Marrows 在 JavaOne Brazil 大会上提到,能够接近 Java 开发者并使用 Java 类库,这也是优势。此外他告诉我们,

…我们非常欣赏 JVM 带来的力量和灵活性,这能够支持我们未来所要进行的任何改进。

更一般的意义是,我们趁此机会简化并替换了我们迄今为止所开发的 MagikSF 环境的某些部分,如图形支持和文件 I/O 等。我们认为这种事情以后做的话,工作量只会多不会少。

JVM 上的语言越来越多,Magik 就是其中之一,其他还包括 Groovy、Jruby 和 Nashorn 等,这些语言都用到了 invokeDynamic 指令。JSR 292 真正帮助 JVM 成为一种通用的编程语言环境。

参考英文原文 GE Energy Uses InvokeDynamic to Bring Magik to the JVM

2012-12-25 02:061369
用户头像
臧秀涛 略懂技术的运营同学。

发布了 300 篇内容, 共 133.6 次阅读, 收获喜欢 35 次。

关注

评论

发布
暂无评论
发现更多内容

【译】TypeScript的Record类型说明

废材壶

typescript

Android Studio 4

android 程序员 移动开发

Android VideoPlayer

android 程序员 移动开发

Android WebView常见问题

android 程序员 移动开发

Android 三类框架的理解以及MVVM框架的使用

android 程序员 移动开发

Android Material Design尝鲜

android 程序员 移动开发

Android C++系列:JNI基本操作

轻口味

android 11月日更

Android OpenCV(三十七):轮廓外接多边形

android 程序员 移动开发

关于调度器的一些思考

Rayjun

调度器 Go 语言

Android TextView的属性与应用

android 程序员 移动开发

Android P 适配指南

android 程序员 移动开发

[ CloudWeGo 微服务实践 - 06 ] 服务发现(1)

baiyutang

golang 微服务 11月日更

Nebula 分布式图数据库介绍

Se7en

Android SpannableString详细解析

android 程序员 移动开发

Android Studio 插件

android 程序员 移动开发

Android Switch控件修改样式

android 程序员 移动开发

android 三级级联筛选列表

android 程序员 移动开发

Android Native Crash 收集

android 程序员 移动开发

Android O 新特性:自适应图标(Adaptive Icons)(1)

android 程序员 移动开发

Android O 新特性:自适应图标(Adaptive Icons)

android 程序员 移动开发

Android Studio 教程:入门开发第一个程序

android 程序员 移动开发

Android UI--ViewPager扩展Tab标签指示

android 程序员 移动开发

Android View 绘制流程

android 程序员 移动开发

Android Zygote 从何而来?揭开Android系统启动的面纱

android 程序员 移动开发

android okhttp异步请求使用详解 (2)

android 程序员 移动开发

在Electron中简单实现拖拽功能

废材壶

node.js 大前端 Electron

Android SDK 网络模块解析

android 程序员 移动开发

Android _ 从 Dagger2 到 Hilt 玩转依赖注入(一)

android 程序员 移动开发

入门Node.js 处理错误

废材壶

node.js 大前端

Android SDK 网络模块解析(1)

android 程序员 移动开发

Android Studio安装更新终极解决方式

android 程序员 移动开发

GE Energy利用InvokeDynamic指令将Magik移向JVM_Java_Charles Humble_InfoQ精选文章