如果在编译时无法进行地址绑定,则在加载/链接或运行时完成,将相对(或者我们可以称它们为可重定位地址)地址与实际物理地址相关联。此外,CPU 还会在绑定物理地址之前将这些相对地址转换为逻辑地址。
从逻辑到物理的转换对我来说是一个已知的概念。但是,我对那些相对寻址感到困惑(AFAIK,他们称之为相对,因为它们是由编译器相对于零给出/分配的)。我不确定(在字节码中)使用什么相对地址,或者它们是否真的需要,或者它们甚至与逻辑地址相同?
如果在编译时无法进行地址绑定,则在加载/链接或运行时完成,将相对(或者我们可以称它们为可重定位地址)地址与实际物理地址相关联。此外,CPU 还会在绑定物理地址之前将这些相对地址转换为逻辑地址。
从逻辑到物理的转换对我来说是一个已知的概念。但是,我对那些相对寻址感到困惑(AFAIK,他们称之为相对,因为它们是由编译器相对于零给出/分配的)。我不确定(在字节码中)使用什么相对地址,或者它们是否真的需要,或者它们甚至与逻辑地址相同?
Java 字节码在比本地机器码高得多的抽象级别上运行。根本没有内存地址的概念——方法被象征性地引用。
考虑 Java 字节码的最简单方法是它与 Java 语言的初始版本几乎是 1:1。编译器会做一些事情,比如将局部变量转换为数字索引,将控制流转换为 goto,但在大多数情况下,它与原始代码非常相似。
JVM 负责在运行时将字节码解释或编译为本机代码。
你混淆了很多概念。相对地址只是需要将基地址转换为绝对地址的地址。这种转换可以通过多种方式发生。一种方法是在加载时转换它们,但它们也可以与 CPU 指令一起使用,这些指令本质上支持在需要访问内存位置时正确进行数学运算的相对寻址。
如果操作系统支持虚拟内存,则在普通进程中使用的所有地址都是逻辑地址,无论它们是相对引用还是绝对引用。从逻辑地址到物理地址的转换超出了应用程序的范围,并且独立于您在问题中提到的任何其他概念。
类文件格式不根据内存位置进行操作。
如果您想在更高级别上应用术语“绝对”和“相对”,则常量池索引是绝对的,因为它们不需要基础索引来识别实际索引。尽管如此,当您想在加载的文件中找到内存位置时,您不仅必须使用加载类文件的地址,还必须将整个常量池解析为所需的项,因为常量池有不同的字节大小。因此,通常根本不查找项目。相反,整个池在一次传递中被转换为具有恒定项目大小的 JVM 特定表示,稍后,JVM 可能会查找该表的条目,而这与类文件的内存位置无关。
在字节码指令中,使用了相对偏移量,这需要添加当前指令的位置以获得绝对位置,但请注意这不适合您问题中命名的概念。绝对位置仍然是指令序列中的位置,因此在谈论地址时相对于代码的内存位置。此外,没有使用相对偏移量,因为“在编译时无法绑定”,生成的绝对位置在编译时是已知的。Java 字节码指令集只是定义为使用相对偏移量以允许更紧凑的代码。从指令集的角度来看,我们可以说它本质上支持相对寻址。JVM 如何实际实现其执行取决于 JVM。
既然你提到了JVM的本地代码生成,当JVM生成本地代码时,它知道代码的目标地址,可以自由决定使用相对地址还是绝对地址,只要它适合。
正如已经提到的,上述所有事情都发生在一个进程中,因此如果操作系统使用虚拟内存,那么这一切都是根据操作系统可能调整的逻辑地址,例如通过 MMU。这些概念是不相关的。
在 Java 中获取对象的内存地址实际上是没有意义的:因为 JVM 正在管理所有这些。
换句话说:JVM 将对象“放置”到合适的位置;它们甚至可以被“移动”;例如在垃圾收集期间。
换句话说:作为一名 Java 程序员,你不在乎。如果你愿意的话;您对此无能为力。