java - 继承是否会更改使用 Unsafe 类获得的字段的偏移量?还是取决于具体的虚拟机实现?

标签 java jvm

当我试图理解“Unsafe.objectFieldOffset”时,我对代码中的注释感到困惑。

// Any given field will always have the same offset, and no two distinct fields of the same class will ever have the same offset.

这是否意味着我获得了抽象类中某个字段的偏移量,该字段在实现类中仍然具有相同的偏移量,因为它们是相同的字段?

以下是示例代码,只是为了说明问题:

public abstract class Parent {
    protected Object value;
}
// Because the question is asked for any implementation class, only a simple example is given
public class Son extends Parent {
    public Son(Object value) {
        this.value = value;
    }

    Object useless_1;
    Object useless_2;
    Object useless_3;
    Object useless_4;
}

public class ParentTool {
    protected static final long offset;
    private static final Unsafe unsafe;

    // Initialize static fields
    static {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
            offset = unsafe.objectFieldOffset(Parent.class.getDeclaredField("value"));
        } catch (Throwable e) {
            throw new Error(e);
        }
    }

    // Hope this method can get and set the fields correctly
    protected static Object getAndSetValue(Parent parent, Object newValue) {
        return unsafe.getAndSetObject(parent, offset, newValue);
    }
}

用于测试的启动类如下

public class Program {
    public static void main(String[] args) {
        Son son = new Son("hello");
        Object value;

        value = ParentTool.getAndSetValue(son, "world");
        System.out.println(value == "hello"); // true
        value = ParentTool.getAndSetValue(son, "test");
        System.out.println(value == "world"); // true
    }
}

运行结果符合预期

true
true

“getAndSetValue”是否始终适用于继承 Parent 的任何类? 这取决于具体的虚拟机实现吗?

我使用的JDK版本如下所示

OpenJDK 64-Bit Server VM Corretto-8.222.10.3

这个问题是出于对 Unsafe 类的好奇而提出的。如果这个问题太宽泛或不适合放在这里,请在评论中告诉我以改进或删除该问题。

最佳答案

子类通常共享父类的结构,可能会在所有父类字段之后添加更多字段。这并不是 Java 所特有的——其他语言(例如 C++)中的继承也是以类似的方式实现的。这使得可以有效地使用子类作为父类的实例,而无需动态类型检查。

因此,该字段的偏移量在父类及其所有后代类中将保持相同。 JVM 不需要这样做,但我知道的所有合理实现都遵循此规则。

严格来说,Unsafe 类已经是特定 JVM 的实现细节,因此根据定义,所有有关 Unsafe 的语句都是特定于 VM 的。

关于java - 继承是否会更改使用 Unsafe 类获得的字段的偏移量?还是取决于具体的虚拟机实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59315097/

相关文章:

java - 类、方法及其成员存储在内存中的什么位置?

java 哈夫曼树优先级

java - 在 Java 中使用 lambda 表达式多次执行一个方法

java - Android 上 Java 中的文件路径

java - 如何从给定数组中查找元素?

java - 指定 java 代理的类路径

java - WatchService 锁定了一些文件?

java - 内存不足何时发生?

java - Rational Rhapsody 调试 JVM

Java JVM 时区名称通过 java.text.SimpleDateFormat