Java 链接器如何工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6440310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:54:07  来源:igfitidea点击:

How Java linker works?

javalinkerjvmspecifications

提问by Kirill Dubovikov

I want to know how Java linker works. Specifically, in which order it combines classes, interfaces, packages, methods and etc into jvm-executable format. I have found some information here, but there is not so much information about linking order.

我想知道 Java 链接器是如何工作的。具体来说,它以什么顺序将类、接口、包、方法等组合成 jvm-executable 格式。我在这里找到了一些信息,但没有太多关于链接顺序的信息。

回答by Thorbj?rn Ravn Andersen

There is no such thing as a Java "linker". There is, however, the concept of a classloader which - given an array of java byte codes from "somewhere" - can create an internal representation of a Class which can then be used with newetc.

没有 Java“链接器”这样的东西。然而,有一个类加载器的概念 - 给定来自“某处”的 Java 字节码数组 - 可以创建一个类的内部表示,然后可以与new等一起使用。

In this scenario interfaces are just special classes. Methods and fields are available when the class has been loaded.

在这种情况下,接口只是特殊的类。加载类后,方法和字段可用。

回答by Michael Borgwardt

First of all: methods are always part of a class. Interfaces are basically just special classes, and packages are just a part of the fully qualified name of a class with some impact on visibility and the physical organization of class files.

首先:方法始终是类的一部分。接口基本上只是特殊的类,包只是类的完全限定名称的一部分,对可见性和类文件的物理组织有一些影响。

So the question comes down to: how does a JVM link class files? The JVM spec you linked to says:

所以问题归结为:JVM 如何链接类文件?您链接到的 JVM 规范说:

The Java programming language allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that the semantics of the language are respected, that a class or interface is completely verified and prepared before it is initialized, and that errors detected during linkage are thrown at a point in the program where some action is taken by the program that might require linkage to the class or interface involved in the error.

For example, an implementation may choose to resolve each symbolic reference in a class or interface individually, only when it is used (lazy or late resolution), or to resolve them all at once, for example, while the class is being verified (static resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.

Java 编程语言允许在链接活动(以及,由于递归,加载)发生时具有实现灵活性,前提是语言的语义得到尊重,类或接口在初始化之前经过完全验证和准备,并且在链接期间检测到的错误在程序中的某个点被抛出,在该点程序采取了可能需要链接到错误中涉及的类或接口的某些操作。

例如,一个实现可以选择单独解析类或接口中的每个符号引用,仅在使用它时(延迟或延迟解析),或者一次性解析它们,例如,在验证类时(静态解决)。这意味着在某些实现中,解析过程可能会在类或接口初始化后继续。

Thus, the question can only be answered for a specific JVM implementation.

因此,这个问题只能针对特定的 JVM 实现来回答。

Furthermore, it should never make a difference in the behaviour of Java programs, except possibly for the exact point where linking errors result in runtime Errorinstances being thrown.

此外,它不应该对 Java 程序的行为产生影响,除非可能是链接错误导致运行时Error实例被抛出的确切点。

回答by sblundy

Java doesn't do linking the way C does. The principle unit is the class definition. A lot of the matching of a class reference to its definition happens at runtime. So you could compile a class against one version of a library, but provide another version at runtime. If the relevant signatures match, everything will be ok. There's some in-lining of constants at compile time, but that's about it.

Java 不像 C 那样链接。原则单位是类定义。许多类引用与其定义的匹配发生在运行时。因此,您可以针对库的一个版本编译一个类,但在运行时提供另一个版本。如果相关签名匹配,则一切正常。在编译时有一些内联常量,但仅此而已。

回答by Sayat Satybald

As noted previously Java compiler doesn't have a linker. However, JVM has a linking phase, which performed after class loading. JVM spec defines it at best:

如前所述,Java 编译器没有链接器。但是,JVM 有一个链接阶段,它在类加载之后执行。JVM 规范最多对其进行了定义:

Linking a class or interface involves verifying and preparing that class or interface, its direct superclass, its direct superinterfaces, and its element type (if it is an array type), if necessary. Resolution of symbolic references in the class or interface is an optional part of linking.

This specification allows an implementation flexibility as to when linking activities (and, because of recursion, loading) take place, provided that all of the following properties are maintained:

  • A class or interface is completely loaded before it is linked.

  • A class or interface is completely verified and prepared before it is initialized.

  • Errors detected during linkage are thrown at a point in the program where some action is taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error.

如果需要,链接类或接口涉及验证和准备该类或接口、其直接超类、直接超接口及其元素类型(如果它是数组类型)。类或接口中符号引用的解析是链接的可选部分。

该规范允许在链接活动(以及由于递归,加载)发生时具有实现灵活性,前提是维护以下所有属性:

  • 类或接口在链接之前已完全加载。

  • 类或接口在初始化之前经过完全验证和准备。

  • 链接期间检测到的错误会在程序中的某个点抛出,在该点上,程序采取了可能直接或间接需要链接到错误中涉及的类或接口的某些操作。

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4