Compilation 运行时编译和链接是如何发生的?

Compilation 运行时编译和链接是如何发生的?,compilation,linker,runtime,Compilation,Linker,Runtime,在一个教程中,我遇到了一个新概念(对我来说),我从未想过这是可能的。实际上,我认为编译完全是一个运行前的过程。这是教程中的一句话:“编译时间发生在链接时间(当一个或多个编译文件的输出连接在一起时)和运行时(当一个程序被执行时)之前。在某些编程语言中,某些编译和链接可能需要在运行时发生” 我的问题是: 预运行时编译和链接过程是否与运行时编译和链接过程完全不同?如果是,请解释主要区别 在运行时需要编译(链接)的代码段是如何标记的?这些信息保存在哪里?(不同语言之间可能存在差异,如果可能,请给出具体示

在一个教程中,我遇到了一个新概念(对我来说),我从未想过这是可能的。实际上,我认为编译完全是一个运行前的过程。这是教程中的一句话:“编译时间发生在链接时间(当一个或多个编译文件的输出连接在一起时)和运行时(当一个程序被执行时)之前。在某些编程语言中,某些编译和链接可能需要在运行时发生”

我的问题是:

  • 预运行时编译和链接过程是否与运行时编译和链接过程完全不同?如果是,请解释主要区别
  • 在运行时需要编译(链接)的代码段是如何标记的?这些信息保存在哪里?(不同语言之间可能存在差异,如果可能,请给出具体示例)
  • 非常感谢您抽出时间

    运行时编译 我个人知道的最好(最著名)的例子是Java使用的。正如您可能知道的,Java代码正在编译成字节码,可以由Java虚拟机进行解释。因此,不同于让我们说,C++首先被(预处理)编译(并链接)成一个可执行的,它可以直接由OS运行,而不需要任何虚拟机。 Java字节码由VM解释,VM将它们映射到特定于处理器的指令。也就是说JVM执行JIT,JIT接受字节码并(在运行时)将其编译成机器代码。现在我们来回答你的第二个问题。即使在Java中,它也可能取决于您使用的JVM,但基本上有一些代码片段称为“热点”(hotspots),这些代码片段经常运行,并且可能会被编译以提高应用程序的性能。这是在运行时完成的,因为普通编译器没有(或者可能没有)所有必要的数据来正确判断哪些代码段实际上经常运行。因此,JIT需要某种类型的运行时统计信息收集,这种收集与程序执行并行,由JVM完成。收集什么样的统计数据、可以优化什么(在运行时编译)等等取决于实现(由于内存和时间的限制,您显然无法完成普通编译器所能完成的所有工作-我猜这部分回答了第一个问题?您并没有编译所有内容,通常在运行时编译中只支持有限的一组优化).您可以尝试查找此类信息,但根据我的经验,通常这些信息的记录非常糟糕,很难找到(至少在涉及官方来源时,而不是演示文稿/博客等)

    运行时链接

    链接器是一对不同的鞋子。我们不再使用java示例,因为它实际上没有像C或C++那样的链接器(而是有一个类加载程序,它负责加载文件并将其全部放在一起)。 通常,链接是在编译步骤(静态链接)之后由链接器执行的,这有优点(无依赖项)和缺点(更高的内存印记,因为我们无法使用共享库,当库号更改时,您需要重新编译源代码)

    运行时链接(动态/后期链接)实际上是由操作系统执行的,操作系统链接器的工作是首先加载共享库,然后将它们附加到正在运行的进程。此外,还有不同类型的动态链接:显式链接和隐式链接。由于版本号是动态的,因此不必在版本号更改时重新编译源代码还有库共享,但也有缺点,如果您有不同的程序使用同一个库,但需要不同的版本(查找DLL hell),那该怎么办呢

    同样,这一切是如何完成的,它是如何决定什么和如何链接的,是特定于操作系统的,例如微软有这个概念