JVM 如何区分 Scala 字节码和 Java 字节码?

How JVM distinguish between Scala bytecode and Java bytecode?

因为 Scala 也生成字节码并由 JVM 执行。我想知道 JVM 如何区分 Scala 字节码和 Java 字节码。谁能解释一下?

 Scalac Myprogram.scala
 java Myprogram

这么说完全没问题?

没有。 Scala 编译成与 Java.

相同的字节码

scalacjavac都生成字节码。 JVM不关心字节码是怎么产生的,对JVM来说都是一样的。

但是,scalajava 设置启动 CLASSPATH 的方式不同,因此如果您的代码包含 Scala 运行时库调用,并且很可能会调用,则需要 运行通过 scala,而不是 java

可以 使用 java 手动设置引导 CLASSPATH,如果你绝对必须这样做,但是为什么要在 scala 时进行所有这些额外的工作会为你做吗?

Scala 编译为正常的 Java 字节码,因此 JVM 似乎没有任何区别。 Java 没有的 Scala 额外功能是通过编译时间传递和运行时辅助函数的组合实现的。如果反汇编生成的 Scala 类,您可能会看到大量调用 Scala 运行时来处理装箱和拆箱参数等内容。

I am wondering How JVM distinguish between Scala bytecode and Java bytecode.

没有。没有 Scala 字节码这样的东西。 Scala 编译器编译成 JVM 字节码。就像Java编译器也编译成JVM字节码一样。

JVM 对 Scala 一无所知。它对 Java 也一无所知。它也不了解 Groovy、Clojure、Kotlin、Ceylon、Fantom、Ruby、Python、ECMAScript 或任何其他约 400 种编程语言,这些语言在JVM.

JVM 只知道一种语言:JVM 字节码。

请注意,这与任何其他机器(无论是否虚拟)都没有什么不同。 CLR 只知道 CIL,它对 C#、VB.NET 或 F# 一无所知。 Intel Core CPU 只知道 AMD64 和 x86 机器码,它对 C、C++、Objective-C、Swift、Go、Java、Python 一无所知. CPython VM 只知道 CPython 字节码,它对 Python.

一无所知

一图胜千言

标准中定义的字节码,从执行者的角度来看是一样的。但是当您使用调试器时,需要更多信息来匹配正确的语言和源文件。

指示生成 JVM 字节码的源代码的唯一方法是通过可选的 class 属性 SourceFile(来自 Java 1.0.2)和 SourceDebugExtension(来自 Java 5.0)。 https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.10 和 11

附加信息将给出源中各种对象的行号LineNumberTable,这也是可选的。 https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.12

您可以找到其他 JVM 规范的等效项。

IDE 使用它们来获取 JVM 的上下文 class,但它们是可选值,调试信息取决于编译器。

所以它可以是一个知道编译器是什么的信息,但你不能依赖它作为确定的信息。如果它被定义,它应该在编译器定义中。

使用 scalac,您可以使用 -g 选项切换信息存储,与 javac 相同,除了 notc,因为 Java 不管理 TCO:

g:{none,source,line,vars,notc} "none" generates no debugging info, "source" generates only the source file attribute, "line" generates source and line number information, "vars" generates source, line number and local variable information, "notc" generates all of the above and will not perform tail call optimization.

默认line

要让类加载器从 class 文件中检索信息,您可以使用开源库 ASM:http://asm.ow2.org/

你也可以自己解析class文件或内部存储,检索class属性不是很困难。