当运行一个'.scala'程序时,Scala运行时/REPL背后到底发生了什么?

19

当我从命令行运行以下类似内容时,实际上会发生什么?

> scala hello.scala

Scala会生成一个hello.class文件,执行完之后会被丢弃吗?还是在这种情况下Scala会像解释器一样运行?我的意思是,当然,对于Java我不能做同样的事情:

> java hello.java
1个回答

24

是的,确实生成了hello.class文件。编译器将你的代码放在一个Main对象内部进行编译,然后执行Main.main,假设hello.scala是:

println(args.mkString)
println(argv.mkString)

如果你使用-Xprint:parser选项运行:scala -Xprint:parser hello.scala foo bar,你将会看到代码被重写的过程:

package <empty> {
  object Main extends scala.ScalaObject {
    def <init>() = {
      super.<init>();
      ()
    };
    def main(argv: Array[String]): scala.Unit = {
      val args = argv;
      {
        final class $anon extends scala.AnyRef {
          def <init>() = {
            super.<init>();
            ()
          };
          println(args.mkString);
          println(argv.mkString)
        };
        new $anon()
      }
    }
  }
}

这段代码被编译(我认为是到内存文件系统,但我不确定),并且执行。查看ScriptRunner,我发现在默认的临时文件夹下创建了一个临时目录。例如,在我的系统上看到了一堆%TEMP%/scalascript*文件夹。

请注意,即使在解释器中,代码也不是解释的。有关更多信息,请参见Scala: Is there a default class if no class is defined?(它的确正在被重写、编译和评估)。


有一个名为Main的类,怎么会有一个名为hello.class的类呢? - nafg
@nafg,是的,从“-Xprint:parser”中可以看出,该类可能被称为Main $,而不是实际叫做hello.class。我理解这个问题是,是否有一个编译、运行和丢弃的类?并不是特别指它是否叫做hello.class... - huynhjl
那么如果它真的创建了这些文件,两个Scala脚本不会互相覆盖吗? - nafg
@nafg,类文件被创建在临时目录下,该目录位于System.getProperty("java.io.tmpdir")。请参见https://github.com/scala/scala/blob/2.10.1/src/compiler/scala/tools/nsc/ScriptRunner.scala#L105。该目录会在脚本退出时被清理。 - huynhjl
我认为你可以做到。这只会将类文件创建到不同的目录中(目录后缀带有特定于该运行的一些随机/唯一数字)... - huynhjl
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接