My question is related to:
What actually happens when we have something like this in our code:
(new SomeClass()).longMethod();
Is there still some sort of unnamed (strong ?) reference pointing to the newly created object on Heap put on Stack?
If nothing is on Stack, then how does Garbage Collector know to preserve the object for the duration of the method?
Is it possibly the same as
{
// very local scope
SomeClass throwAwayRef = new SomeClass();
throwAwayRef.longMethod();
}
As far as your code is concerned, the instance is gone as soon as you no longer have a reference to it.
no. When you later "initialize" the variable, you are assigning a reference to the variable. You are not copying the fields of the object.
We can break the life of an object into three phases: creation and initialization, use, and destruction. Object lifecycle routines allow the creation and destruction of object references; lifecycle methods associated with an object allow you to control what happens when an object is created or destroyed.
When an object is created, memory is allocated to hold the object properties. An object reference pointing to that memory location is also created. To use the object in the future, that object reference has to be stored as a local variable or as an object member variable. Code section 4.30: Object creation.
You can look at the bytecode for insight:
0: new #16 // class SomeClass
3: dup
4: invokespecial #18 // Method SomeClass."<init>":()V
7: invokevirtual #19 // Method SomeClass.longMethod:()V
new
actually allocates the object, a reference to which is pushed on the stack. dup
duplicates the top-of-stack; now the top two stack items are references to the newly created object.invokespecial
here calls the constructor of SomeClass
, popping the stack; now the stack consists of just a single reference to our SomeClass
instance. The instance is not GCed because a reference to it exists on the stack.invokevirtual
here calls longMethod
. Again, the instance is not GCed because a reference to it still exists on the stack (and is popped after the method completes, after which it is eligible for GC).(new SomeClass()).longMethod();
is not the same as
{
// very local scope
SomeClass throwAwayRef = new SomeClass();
throwAwayRef.longMethod();
}
at the bytecode level, since the latter involves an astore
and an aload
. However, the two are certainly functionally equivalent. The SomeClass
instance still becomes eligible for GC after longMethod
completes (the stacks for the two snippets will look identical when invokevirtual
is executed).
Reference:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With