1

Say I have the following stream:

List<Other> list = Stream
    .of(
        new MyObject(), 
        new MyObject()
    )
    .map(this::mapToOther)
    .collect(toList())
;

So after this is executed, I will certainly get a list of Other in memory, but I wonder whether the source objects (i.e. MyObject) are still "alive" in memory (I mean not yet garbage collectable)?

5
  • @user1589188 please clarify the moment of time you are asking about. Once list is assigned, everything but it's content is garbage collectible. If the question is about a moment before the second call to mapToOther the situation is not that trivial.
    – Basilevs
    Commented Jan 22 at 4:45
  • BTW, flatMap produces even less obvious behavior.
    – Basilevs
    Commented Jan 22 at 4:50
  • @Basilevs updated. yes, after the list is assigned. Commented Jan 22 at 5:05
  • @Basilevs but you got me into thinking, may be also as the stream goes through each source object, would each of them be GCable right after it completes the map but before all completed the map? Commented Jan 22 at 5:14
  • @user1589188 Probably not, but only because you are using Stream.of(). For a Stream implementation that only instantiates one (or a few) items just in time to feed them to the operation pipeline, any object created in the whole process is definitely GCable when the last operation that has a reference to it completes processing it. Commented Jan 22 at 8:22

2 Answers 2

4

You did not say what ´mapToOther` should or should not do.

So assume:

  • mapToOther has the signature Other mapToOther(MyObject obj), and transforms obj of type MyObject to a new object of type Other

  • it does not keep a reference to obj somewhere else (maybe in some cache)

  • it does not put a reference to obj into the newly created ´Other` object

  • the implementation of the Stream classes is quite sane and takes cares not to create memory leaks

then the source objects are "garbage collectable" right after the assignment. If one of the above assumptions is violated, then the MyObject instances will continue to "live".

To answer your comment:

as the stream goes through each source object, would each of them be garbage collectable right after it completes the map but before all completed the map

This ultimately depends on the underlying implementation of Stream.of and map. The Stream documentation discourages multiple consumptions of a stream, hence there is no mandatory reason for the elements to be kept in scope right after they were processed. On the other hand, Stream.of uses varargs, so all of the instances of MyObject are first created and then put into an array internally before .of is executed. The most straightforward implementation of of and map might simply keep the elements in that array internally. So I would usually expect the elements are not garbage collectable before the assignment is completed.

2
  • Thank you and especially for addressing my comment as well. By "right after the assignment", I believe you mean after the map right? Not necessarily after the collect, no? Commented Jan 24 at 2:10
  • 1
    @user1589188; no, I meant "right after the full assignment." - then it is sure the objects are garbage collectable. Assuming the "map" for all objects is completed before the "collect" operation starts is a misunderstanding of what happens here. See stackoverflow.com/q/29915591 for a better understanding. It may happen that the processed subset of the objects are GC-able already in the middle of the collect operation, but it ulitmatemaly depends on the underlying implementation.
    – Doc Brown
    Commented Jan 24 at 6:19
4

As far as garbage collection goes it does what this does:

Other other = mapToOther(new MyObject());

That is, if mapToOther() leaves other holding a hard reference to your MyObject instance they will live and die together. If not the MyObject instance is eligible for garbage collection when you hit the semicolon. These things have been called nameless temporary objects or anonymous objects. Not every object gets directly associated with an identifier like a variable. But they can live forever in an object graph. That's one of the reasons circular references are such a bad thing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.