【发布时间】:2021-09-29 12:34:30
【问题描述】:
以下是一个假设问题。我很感兴趣,如果可以通过任何可以想象的晦涩手段(不安全的 API、JNI、ASM 等)以某种方式实现效果。这不是 XY 问题,我从不打算编写这样的代码!我只是对内部结构感到好奇。
假设我们在 Java 中有这个非常简单的层次结构:
class Cupcake {
public String kind;
// ...
}
class WholeRealityItself extends Cupcake {
public Object[] wholeMatterOfUniverse;
// transform internal state because reasons
public performBigBangAndFluctuateACupcake() {
// ... chaotic spacetime fluctuations produce a cupcake
this.kind = "quantum_with_sprinkles";
}
}
我们的流程如下:
WholeRealityItself reality = new WholeRealityItself();
reality.performBigBangAndFluctuateACupcake();
Cupcake cupcake = (Cupcake) reality; // upcast
// from now on the object will be only accessed via it's supertype and never downcast
言归正传:
- 我们创建一个子类型的对象,它分配了很多内存。
- 我们对此子类型对象执行一些内部状态转换。
- 我们将对象向上转换为它的超类型,从现在开始,我们将只通过它的超类型来引用它,并且永远不会向下转换
所以现在我们的 JVM 持有一个 Cupcake 对内部 WholeRealityItself 对象的引用,该对象的内存(程序员知道)将永远不会再被访问。是的,我知道引用和实际分配的对象是两个不同的东西,向上转换/向下转换使程序只是“重新解释”一个对象。
完全忽略了这样一个事实,即这种可憎的代码是不可用的,应该用理智的构建器/工厂/副本或其他东西代替,只是为了论证的缘故假设我们想要这样。 重点不在于如何达到同样的效果,而是以下是否可行:。
您能否强制缩小实际分配的 OBJECT 以将其内部结构从 WholeRealityItself 转换为 Cupcake 并强制释放 wholeMatterOfUniverse?
AKA - 你能以某种方式 对底层分配的OBJECT 进行切片吗?关于对象切片的最后一个问题来自大约 10 年前。
【问题讨论】:
-
好吧,为了让这在理论上成为可能,需要
WholeRealityItself成为final,这样我们就可以保证没有人可以编写一个仍然可以访问wholeMatterOfUniverse的子类,例如通过在equals的覆盖中使用它。 -
但我很确定在 JVM 中不可能有这样的事情 - 例如,这将为 C++ 中可能遇到的所有对象切片问题打开大门,而 Java 旨在避免这样的陷阱。
-
即使您编辑中的措辞是错误的:转换不会使 Java 重新解释一个对象(这就是它在 C 中的工作方式以及在 C++ 中的某些转换)。但在 Java 中,演员表只会重新解释引用。这是一个细微的差别,但由于您询问的是处于可实现性边缘的功能,因此这种区别很重要。
标签: java memory-management allocation