Modern JVM's sometimes relocates objects in memory during garbage collection even though the value of System.identityHashCode(object)
remain the same for the lifetime of the object. What I do not understand is why do JVM relocate objects in memory?
-
2To perform garbage collection. There are several schemes for garbage collection, some which involve copying objects from one space to another to "compact" things, others which involve moving long-lived objects to separate spaces, so they don't have to be scanned for GC as often. (It is quite possible to have a scheme that *does not* move objects, and, in fact, a JVM with such a scheme was the world-record performer for several years.) – Hot Licks Aug 31 '13 at 17:11
-
@HotLicks, you mean old and young(eden, survivors) generation? – Aliaksei Bulhak Aug 31 '13 at 17:14
-
@AlekseiBulgak - A number of different terminologies are used by different groups -- there's not much point in trying to be specific/precise in that regard. – Hot Licks Aug 31 '13 at 17:17
-
@HotLicks Which JVM was the *world-record performer*? – Geek Aug 31 '13 at 17:19
-
IBM iSeries "Classic" JVM. For 3-4 years straight it held the record for server performance. Fell behind when IBM decided to stop investing in it, in favor of J9. – Hot Licks Aug 31 '13 at 17:24
-
http://mechanical-sympathy.blogspot.co.uk/2013/07/java-garbage-collection-distilled.html – assylias Aug 31 '13 at 17:30
-
FYI: `System.identityHashCode(object)` values are not unique. – Gray Sep 01 '13 at 14:43
-
1@Gray I didn't say that the values are unique. I said that the value for an object do not change during the lifetime of the object. Am I missing anything from your comment? – Geek Sep 01 '13 at 14:45
-
No. I'm just pointing out that people think the identity hash code is like a pointer or reference to the object. It isn't and if you generate a million objects you will see multiple objects with the same identity hash code. That's why it was labeled as a FYI. – Gray Sep 01 '13 at 14:49
-
@SotiriosDelimanolis the heap data structure mentioned in your link has nothing whatsoever to do with this question. Have you read it? – user207421 Sep 01 '13 at 23:46
2 Answers
If the memory gets fragmented (i.e. bits and pieces in between are removed) then memory access speed can be improved by defragmenting it. Moreover, defragmenting it opens up larger straits of memory, for large objects.
Edit for clarity: As posted in the comments below this answer, the Garbage Collection algorithms normally maintain 'zones' of memory. Some are meant to last long, and some are not. The algorithm differs on different JVMs, but it usually includes moving objects from one zone to the other in order to empty a zone completely, if it's already almost empty. That zone can then be made available as a whole. And the JVM is quite clever in discovering which objects are meant to last and which aren't, but sometimes it has to adapt its strategy and relocate an object.

- 2,830
- 1
- 15
- 27
-
3That is not the only reason - for example GC that have young/old generations move stuff around during minor/major GCs - that allows efficient discarding of unreachable objects – assylias Aug 31 '13 at 17:34
-
1@assylias may be you should either edit this answer or post a new answer. Your comment received a lot of upvotes and it is not covered in the answer. – Geek Sep 01 '13 at 14:46
-
@Gray What I meant is: once all the objects that are reachable in the young generation have been moved, there is no need to delete the unreachable ones: the whole zone can then be considered as available. That makes creating short lived objects "free" (apart from the cost of more frequent GCs). I agree that the two concepts are close. – assylias Sep 01 '13 at 16:03
-
@Gray: the point of generational garbage collection is to have objects with a short lifetime in a separate space, so they can be collected without needing to scan the whole heap. – ninjalj Sep 01 '13 at 16:05
-
2@Gray: no, you're confusing generational GC with compacting GC and/or copying GC. Generational GC is about separating objects with shorter lifetimes from the rest of objects; then, different generations may be collected using different GC strategies, e.g: a copying collector for the young generation (which improves locality and reduces fragmentation), and a mark-sweep collector for the old generation. – ninjalj Sep 01 '13 at 16:15
-
Ok. I'm exposing my ignorance on the subject. So yes, I agree with Geek. You should expand your comment @assylias and point out that relocation is an important part of GC performance because it allows objects to be copied between memory pools (i.e. relocated) which allows for multiple GC algorithms depending on the pool.. – Gray Sep 01 '13 at 16:32
-
@Gray I am in low-procrastination mode these days - so maybe later! But feel free to add an answer if you like! – assylias Sep 01 '13 at 18:58
-
I've posted a new answer @assylias. Feel free to edit it or comment on it if I've screwed something up. – Gray Sep 03 '13 at 12:46
What I do not understand is why do JVM relocate objects in memory?
For posterity I thought it was good to summarize some comments on the other answer here. @assylias prolly should be writing this but he sounds busy. As @Ghostkeeper points out, one of the important benefits of relocatable objects is to lower (or remove) the problems inherent in memory fragmentation. Longer lasting smaller objects can be moved next to other objects of a similar size to open up contiguous free space for use by larger objects.
But an even more important reason why object relocation is so important is for memory and garbage-collection performance. Most modern JVMs implement a generational garbage-collector which maintains a number of different memory pools. These pools are often visible by using jconsole and connecting to your running application. See this answer for more info: How is the java memory pool divided?
Short term objects go into one pool and a high performance GC algorithm can run just on them since so many objects are immediately collected for reuse. By using information about the pool, the GC can easily determine that an object is unreachable without having to traverse the entire reference tree. For example, if you have a log-line like the following, the implied StringBuilder
and resulting String
are created and then can immediately be collected from the short-term object pool:
logger.info("automation run took " + diffMillis + "ms");
// when we reach this line, the StringBuilder and String are no longer in use
Because objects are relocatable, when the high performance GC algorithm finds an object in the short-term pool that is still in use, it is copied (relocated) to another pool and the references to the object are updated with the new location. Then the JVM has a clean short-term memory pool which it can begin to fill again. Objects in the mid-term or long-term memory pools are collected or relocated using more expensive GC algorithms (mark-and-sweep) that run less frequently. This ability to utilize different GC algorithms depending on which pool the object is in and being able to migrate objects between pools is a critical part of the modern, high-performance, GC systems in today's JVMs.
So the ultimate goal of relocatable objects is both overall memory performance and defragmentation.