12

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();
}
Community
  • 1
  • 1
PM 77-1
  • 12,933
  • 21
  • 68
  • 111

3 Answers3

7

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:

arshajii
  • 127,459
  • 24
  • 238
  • 287
3

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.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

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

Community
  • 1
  • 1
Adam Finley
  • 1,550
  • 1
  • 16
  • 28
  • 3
    more proof or an example please – jgr208 Jun 17 '15 at 17:29
  • The height method could store `this` somewhere, so Oracle is not quite right here. Without knowing the code of height, we just don't know whether the reference is stored somewhere. – Ingo Jun 17 '15 at 20:14
  • @Ingo Well I'm assuming they meant `java.awt.Rectangle` which does not have that behavior, but you make a good point for the general case. – Adam Finley Jun 17 '15 at 20:23