编译器生成的相对地址以及它们如何在(最好是 java)字节码中表示?

Compiler-generated relative addresses and how they are represented in (preferably java) bytecode?

如果在编译时无法进行地址绑定,则可以在 load/link 或运行时完成,将相对(或者我们可以称它们为可重定位地址)地址与实际物理地址相关联。另外,CPU 还会在绑定物理地址之前将这些相对地址转换为逻辑地址。

从逻辑到物理的转换对我来说是一个众所周知的概念。但是,我对那些相对寻址感到困惑(AFAIK,他们之所以称之为相对,是因为它们 given/assigned 相对于编译器的零)。我不确定什么相对地址用于(在字节码中)或者是否真的需要它们,或者它们甚至与逻辑地址相同?

Java 字节码在比本机代码更高的抽象级别上运行。根本没有内存地址的概念 - 方法以符号方式引用。

想到 Java 字节码的最简单方法是它实际上 1:1 与 Java 语言的初始版本。编译器做了一些事情,比如将局部变量转换为数值索引,将控制流转换为 goto,但在大多数情况下,它与原始代码非常相似。

JVM 负责在运行时将字节码解释或编译成本机代码。

在 Java 中获取对象的内存地址实际上毫无意义:因为 JVM 正在管理所有这些。

换句话说:JVM "puts" 对象应该在任何合适的地方;他们甚至可以 "moved" 左右;例如在垃圾收集期间。

换句话说:作为一个 Java 程序员,你不在乎。如果你愿意的话;你对此无能为力。

你混淆了很多概念。相对地址只是需要将基地址转换为绝对地址的地址。这种转变可以通过多种方式发生。 一种 方法是在加载时转换它们,但它们也可以与 CPU 指令一起使用,这些指令本质上支持相对寻址,当内存位置需要时进行正确的数学计算已访问。

如果操作系统支持虚拟内存,则在普通进程中使用的所有地址都是逻辑地址,无论它们是相对引用还是绝对引用。从逻辑地址到物理地址的转换超出了应用程序的范围,并且独立于您在问题中提到的任何其他概念。

class 文件格式不根据内存位置进行操作。

如果您想在更高级别上应用术语“绝对”和“相对”,常量池索引是绝对,因为它们不需要基本索引来识别实际指数。尽管如此,当你想在加载的文件中找到内存位置时,你不仅要使用 class 文件加载到的地址,你还必须解析整个常量池直到所需的项目,因为常量池有不同的字节大小。因此,通常根本不会查找项目。取而代之的是,整个池被转换为 JVM 特定的表示形式,在一次传递中具有恒定的项目大小,之后,JVM 可能会查找 table 的条目,这与 class 文件的内存无关位置,而不是。

在字节码指令中,使用了相对偏移量,这需要添加当前指令的位置以获得绝对位置,但请注意这不符合您问题中提到的概念。绝对位置仍然是指令序列中的位置,因此,在谈论地址时,相对于代码的内存位置。此外,不使用相对偏移量,因为“在编译时不可能绑定”,由此产生的绝对位置在编译时是已知的。 Java 字节代码指令集只是定义为使用相对偏移量以允许更紧凑的代码。从指令集的角度来看,我们可以说它本质上支持相对寻址。 JVM实际如何实现它的执行,取决于JVM。

以来,当JVM生成本机代码时,它知道代码的目标地址,并且可以根据需要自由决定使用相对地址还是绝对地址。

如前所述,上面描述的一切都发生在一个进程中,因此如果操作系统使用虚拟内存,则都是根据操作系统可能会调整的逻辑地址,例如通过 MMU。这些概念是不相关的。