9

I know the reason that JVM GC loves short-live object because it can be collected in minor GC. But why does JVM GC love immutable objects?

EDIT: Charlie Hunt says that GC loves immutable objects in his presentation.

Thanks

Jacky
  • 8,619
  • 7
  • 36
  • 40

3 Answers3

8

If the GC can know that an object doesn't contain any references to any gen0 objects, then it can be ignored when performing a gen0 collection. Likewise if an object doesn't contain any reference to any gen0 or gen1 objects, it may be ignored when performing a gen1 collection. The more objects can be ignored during a collection, the faster that collection will be.

If an object survives a gen0 GC, it can be sure that any gen0 object to which it had held a reference will have been promoted to gen1; likewise if an object which didn't contain any gen0 references survives a gen1 GC, any gen1 references it contained will have been promoted to gen2. Thus, once a object has been examined during a gen0 collection, it need not be examined again until the next gen1 collection, unless it is modified. Likewise an object that's examined during a gen1 collection need not be examined until the next gen2 collection unless it is modified.

Knowing whether objects have been modified is a tricky subject, but the key point is that it's very advantageous for the GC if objects haven't been.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • Thank you, @supercat. I have questions: a) Does "ignore" means it does not trace the object further? b) What is gen0, gen1 and gen2? You mean young and old generation? c) Does GC know whether objects have been modified ? – Jacky Jan 16 '13 at 06:13
  • 1
    @Jacky: By "ignore" I indeed mean "mean not trace further". I mainly use .net which numbers generation 0-2; I think Java implementations have more than just one "young" and "old" generation, but I don't know the details. In order for the GC to take advantage of generations in the "mark" phase, it must know what objects may have been modified since the last GC for each generation. The mechanisms for that are rather complicated. If there were a special means of declaring immutable objects which required that the contents be specified before references could be... – supercat Jan 16 '13 at 16:09
  • 2
    ...passed out of the current execution scope, such objects wouldn't need to have the mechanisms associated with tracking whether they'd changed (since they simply wouldn't change); alternatively, on any system which support virtual-memory mechanisms sophisticated enough to track changes to mutable objects (and even many with VM mechanisms that are far more limited), those same mechanisms could be used to ensure that immutable objects couldn't be changed even by "rogue" code. – supercat Jan 16 '13 at 16:13
  • that makes sense. I will keep this question open for a while in order to see if there are more comments from others. Thanks very much. – Jacky Jan 17 '13 at 05:45
  • 1
    @Jacky: Glad my answer was helpful. Thinking about it a little more, for low-footprint virtual machines that can't afford a card table, but can write-protect large ranges of RAM, perhaps one could have a bit in each object's descriptor which says that it will never again be written, and have the GC move that object to a hardware-write-protected area on the next GC cycle (the GC itself would of course be allowed to bypass the write protection). If a GC cycle occurs during an object's constructor, it would be go into a region with objects that must be scanned in all GC cycles, but... – supercat Jan 17 '13 at 15:23
  • 1
    ...are not eligible for deletion until the next gen1 cycle. After it survives the next gen1 cycle, its "immutability" flag would cause it to move to a region of write-protected objects that don't hold any gen0 or gen1 references. The write-protection wouldn't protect against errant code changing things it shouldn't (since objects wouldn't be write-protected immediately), but would provide absolute protection against objects holding newer references than they're supposed to (which is the fundamental #1 requirement for a non-broken GC). – supercat Jan 17 '13 at 15:27
2

Thanks for the link..found it nice :)

From presentation : GC loves small immutable objects and short lived objects.

Edit:

Smaller objects have short memory footprint which means that after collection there will not be much overhead on memory compaction ( Memory compaction is slow for big object as they leave bigger memory holes after they get reclaimed by GC). And short lived objects are also good as they get collected in minor GC cycles.

rai.skumar
  • 10,309
  • 6
  • 39
  • 55
  • Large object is likely promoted to old generation directly if it can not fit into survival area during minor gc. A worse case, it may be promoted into old generation directly when it is created if it can not fit into the free space of young generation. – Jacky Jan 08 '13 at 13:28
  • Immutable objects have many benefits. I think GC can easily find all immutable objects during tracing. I have not figured out how it can reduce the overhead to take care of them. I believe there are some reasons why Hunt mentioned that. – Jacky Jan 08 '13 at 13:34
  • Yeah, having smaller immutable object is ideal case for optimum performance but he never stresses that GC favors ONLY immutable objects. – rai.skumar Jan 08 '13 at 14:18
2

I found the answer from Brian Goetz's article.

In most cases, when a holder object is updated to reference a different object, the new referent is a young object. If we update a MutableHolder by calling setValue(), we have created a situation where an older object references a younger one. On the other hand, by creating a new ImmutableHolder object instead, a younger object is referencing an older one. The latter situation, where most objects point to older objects, is much more gentle on a generational garbage collector. If a MutableHolder that lives in the old generation is mutated, all the objects on the card that contain the MutableHolder must be scanned for old-to-young references at the next minor collection. The use of mutable references for long-lived container objects increases the work done to track old-to-young references at collection time.

Jacky
  • 8,619
  • 7
  • 36
  • 40
  • I wonder if any noteworthy GC frameworks have a separate heaps for mutable and immutable objects, with the proviso that the immutable heaps wouldn't need card tables. Indeed, if one was trying for a compact framework, I would think one might be able to get decent performance without any card tables if gen1/gen2 mutable objects were scanned (but not moved) on every collection but immutable ones weren't. – supercat Jan 14 '13 at 23:53