Java对象何时完全初始化?

5
众所周知,通过new字节码刚刚分配的对象没有被初始化,因此不是一个java.lang.Object。如果我运行时修改字节码并将该对象传递给方法,JVM会发出警告甚至崩溃(因为我提供的“东西”不是java.lang.Object)。
那么,我的问题是,对象何时“完全”初始化,即成为java.lang.Object?它是在构造函数(<init>)中:
  • 被调用时?
  • 返回时?
  • 在返回之前的某个时间点?
  • 调用java.lang.Object.<init>时?
  • 其他时间?
2个回答

5

从任何给定的<init>方法的角度来看,在调用invokespecial返回后,this值被认为已初始化,无论是在同一类中调用另一个<init>方法还是在超类中调用。

同样地,对于使用new指令创建的对象,在对它们调用<init>方法时被认为已初始化。

请注意,初始化跟踪是局限于方法的。字节码验证是基于方法的,并且每个方法只看到在其中创建的对象和调用的方法。确保无法在构造函数中初始化此值而不调用另一个构造函数的事实,确保它最终会链接到一个java.lang.Object构造函数,除非它抛出异常或进入无限循环。


非常合理的论点。 - xuq01

0

这是一个“Foo”类的方法的字节码

 public <init>()V
   L0
    LINENUMBER 1 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this LFooTest; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

当您尝试创建Foo的新实例时,将调用INVOKESPECIAL java/lang/Object. ()V,然后对象将在堆内存中创建,并将引用返回到堆栈并分配给"this"。因此,在我看来,您的问题的答案应该是“调用java.lang.Object.init()之后”。

实际上,在调用构造函数之前,对象已经存在于堆中。否则,就没有this值可以传递给它。 - Antimony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接