My question is related to:
- Java: What is the purpose of creating an object in the heap with no reference
- Java - Can objects which are executing methods be garbage-collected?
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();
}
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:
- Java bytecode instruction listings
Yes,
new SomeClass().longMethod();
is effectively the same as, especially from a garbage collection standpoint:
{
SomeClass throwAwayRef = new SomeClass();
throwAwayRef.longMethod();
}
The in-line version has an implicit reference to the new object (on the stack). It becomes available for garbage collection as soon as the method call finishes.
Yes, reference to the new object exists on the stack.
straight from Oracle:
To access a field, you can use a named reference to an object, as in
the previous examples, or you can use any expression that returns an
object reference. Recall that the new operator returns a reference to
an object. So you could use the value returned from new to access a
new object's fields:
int height = new Rectangle().height;
This statement creates a new
Rectangle object and immediately gets its height. In essence, the
statement calculates the default height of a Rectangle. Note that
after this statement has been executed, the program no longer has a
reference to the created Rectangle, because the program never stored
the reference anywhere. The object is unreferenced, and its resources
are free to be recycled by the Java Virtual Machine.
source: https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html