继承是否会改变使用 Unsafe class 获得的字段的偏移量?还是要看具体的虚拟机实现?
Does inheritance change the offset of a field obtained with the Unsafe class? Or depends on the specific virtual machine implementation?
当我试图理解"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.
这是否意味着我在摘要中得到了一个字段的偏移量class,这个字段在实现中仍然具有相同的偏移量class,因为它们是相同的字段?
下面是示例代码,只是为了说明问题:
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);
}
}
测试用的启动class如下
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 的 class?
这是否取决于具体的虚拟机实现?
我使用的JDK版本如下图
OpenJDK 64-Bit Server VM Corretto-8.222.10.3
这个问题是出于对不安全 class 的好奇而提出的。如果这个问题太笼统或不适合放在这里,请在评论中让我知道以改进或删除问题。
子 classes 通常共享父 class 的结构,可能会在所有父字段之后添加更多字段。这不是特定于 Java - 其他语言(例如 C++)中的继承以类似的方式实现。这使得在没有动态类型检查的情况下有效地使用子 class 作为父 class 的实例成为可能。
因此,该字段的偏移量在父 class 及其所有后代 class 中将保持不变。 JVM 不需要 这样做,但我知道的所有合理实现都遵循此规则。
严格来说,Unsafe
class 已经是特定 JVM 的实现细节,因此根据定义,所有关于 Unsafe
的陈述都是特定于 VM 的。
当我试图理解"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.
这是否意味着我在摘要中得到了一个字段的偏移量class,这个字段在实现中仍然具有相同的偏移量class,因为它们是相同的字段?
下面是示例代码,只是为了说明问题:
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);
}
}
测试用的启动class如下
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 的 class? 这是否取决于具体的虚拟机实现?
我使用的JDK版本如下图
OpenJDK 64-Bit Server VM Corretto-8.222.10.3
这个问题是出于对不安全 class 的好奇而提出的。如果这个问题太笼统或不适合放在这里,请在评论中让我知道以改进或删除问题。
子 classes 通常共享父 class 的结构,可能会在所有父字段之后添加更多字段。这不是特定于 Java - 其他语言(例如 C++)中的继承以类似的方式实现。这使得在没有动态类型检查的情况下有效地使用子 class 作为父 class 的实例成为可能。
因此,该字段的偏移量在父 class 及其所有后代 class 中将保持不变。 JVM 不需要 这样做,但我知道的所有合理实现都遵循此规则。
严格来说,Unsafe
class 已经是特定 JVM 的实现细节,因此根据定义,所有关于 Unsafe
的陈述都是特定于 VM 的。