読者です 読者をやめる 読者になる 読者になる

nFact

n!

JVM言語がHello Worldを表示するまでの実装(JavaとScala編)

JVM言語

Java Virtual Machine上で動作するプログラミング言語JVM言語と言います。

JVM言語で有名なものだとScalaとかClojureとかGroovyなどが挙げられます。
KotlinとかCeylonとかもこれから流行りそうな雰囲気です。

どの言語も1 + 1レベルだと生成されるバイトコードはほぼ同じ
(iconst_1 iconst_1 iaddとか)ですが、
Hello worldを出力するバイトコードが各言語で違うのでまとめてみました。今のところ2つです。

Java

まずはJava(javac 1.8.0_25)

まずSystemクラスのoutフィールドを取得します。
outPrintStreamクラスのオブジェクトです。
PrintStreamprintlnメソッドに"Hello World"を渡して呼んでいます。
これが基本形になります

Scala

次はScala(2.11.4)です

HelloWorldを表示する部分がSystem.out.println(...)からprintln(...)になっています。
ScalaPredefオブジェクトにprintlnメソッドが定義されていて、そのprintlnメソッドが使用されます。
importが無いじゃん!っていう話ですが、PredefオブジェクトはScala側で暗黙的にimportされています。
つまり、上のコードのprintln("Hello World!")Predef.println("Hello World!")に書き換えても同じ動作をします。

Predefオブジェクトのprintlnは、

scala/Predef.scala at 2.11.x · scala/scala · GitHub

   def println(x: Any) = Console.println(x)

となっていて、Consoleクラスに引数をそのまま渡しているようです。

Console.scalaを見ると、

scala/Console.scala at 2.11.x · scala/scala · GitHub

...
   private val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
...
   def out = outVar.value
...
   def println(x: Any) { out.println(x) }

new DynamicVariable[PrintStream](java.lang.System.out)
JavaSystemクラスのoutフィールドを持ってきているようです。
DynamicVariableクラスは動的スコープをエミュレートするクラスです。
(動的スコープに関しては割愛します)
DynamicVariableを使用して、JavasetOut相当の動きを提供しているようでした。
直接System.out.printlnコンパイルせず、Predef.scalaConsole.scalaを経由して、
Hello Worldが表示されるという実装でした。