About the location of data structure and its inner objects

Jon Masamitsu jon.masamitsu at oracle.com
Wed Aug 28 10:47:43 PDT 2013


On 8/28/2013 1:42 AM, Krystal Mok wrote:
> Hi Lijie,
>
> On Wed, Aug 28, 2013 at 10:46 AM, Lijie Xu <csxulijie at gmail.com> wrote:
>
>> Thank Tao, I think I have a graph of memory layout now. I have another
>> five questions:
>>
>> 1) Can old space's max size be adjusted dynamically by GC while the JVM is
>> running?
>>
>> Yes if you're using UseParallelGC / UseParallelOldGC and
> UseAdaptiveSizePolicy is on (it is on by default). Other GCs in HotSpot
> don't implement adaptive size policy yet.

The maximum size of the heap is fixed at VM initialization.  By default 
the maximum size of the
old generation is also fixed at initialization.  The exceptions are with 
UseParallelGC and UseG1GC.

With UseParallelGC the GC will move space between the young generation 
and the old
generation if UseAdaptiveGCBoundary is turned on.  This does not 
increase the maximum
size of the heap.  There are limits to this movement (i.e., there is a 
minimum size of the
young generation and a minimum size of the old generation that has to be 
observed).

With UseG1GC the young generation is a logical collection of regions and 
the collection
changes dynamically.  Again the maximum size of the heap does not 
increase and there
are limits on the minimum size of the young generation.


>
>
>> 2) I want to know if FullGC will definitely trigger MinorGC, or just
>> reclaim the unreferenced objects in Old/Eden/S0/S1 without object promotion.
>>
>> A "full GC" in HotSpot terms collects the whole GC heap, not just the old
> generation. It doesn't have to do a separate minor GC before a full GC to
> collect the young generation.
> A case for UseParallelGC / UseParallelOldGC is that it defaults to scavenge
> (do a minor GC) right before a full GC. This behavior can be turned off
> with -XX:-ScavengeBeforeFullGC

The exception to a "full GC collects the whole heap" is CMS.  A CMS 
mark-sweep  (and a
concurrent collection is a mark-sweep collection) only collect the old 
generation.

Jon

>
>
>> 3) Whether MinorGC can copy an object directly into Old if the Survior
>> hasn't enough space to hold it currently?
>>
> Yes, it could. That would be called a "premature promotion" / "survivor
> space overflow".
> It is even possible to directly allocate a new object in the old
> generation. Assuming you can read Chinese, refer to this thread for an
> example: http://hllvm.group.iteye.com/group/topic/38293
>
>> 4) Can JVM heap use virtual memory or just physical memory?
>>
>> In HotSpot VM's case, the virtual address space for the whole GC heap is
> allocated up front, during VM intialization, but is then only commited on
> demand. The virtual memory allocated won't be backed by physical memory
> before it's commited.
>
>
>> 5) Can DirectBuffer use virtual memory or just physical memory?
>>
>> A NIO Direct-X-Buffer, if allocated from the Java side, is just a regular
> Java object in the Java heap, acting as a proxy to a backing buffer
> allocated via malloc() on the C heap. Whatever knowledge you have on
> malloc() applies here.
> On the other hand, a Direct-X-Buffer can be created via JNI, too, wrapping
> an existing buffer in native code. [1] You can wrap any piece of native
> memory into a DirectByteBuffer this way.
>
> HTH,
> Kris
>
> [1]:
> http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#NewDirectByteBuffer
>
>
>>
>>
>> On Tue, Aug 27, 2013 at 2:23 AM, Tao Mao <tao.mao at oracle.com> wrote:
>>
>>>   Java always conceptually holds a reference rather than the whole object
>>> body, but you can directly see and use the body in C++.
>>>
>>> Below let me illustrate on the HashMap example?
>>>
>>> Tao
>>>
>>>
>>> On 8/26/13 1:20 AM, Lijie Xu wrote:
>>>
>>>   Hi, folks. I’m confused with the concrete locations of the data
>>> structure and its inner objects in the heap. The questions are below.
>>>
>>> A general question:
>>>
>>> If an object X is decided to be copied into old from new gen by GC, all
>>> the objects which can be reached from X are copied into old too. Or X’s
>>> retained set. Or this statement is wrong.
>>>
>>>
>>>   Two concrete questions.
>>>
>>> Q1: Can an array such as byte[], String[] and Object[] span two
>>> generations?
>>>
>>> I think primitive arrays such as byte[] and int[] cannot span (e.g., a
>>> part of the array exists in eden and the other part exists in old space).
>>> For reference arrays such as Object[], the array itself cannot span but the
>>> items in the arrays can span (i.e., some items exist in new gen while
>>> others exist in old gen). I’m not sure if I’m right and if String[] is as
>>> same as byte[].
>>>
>>>
>>>
>>> Q2: Can ArrayList, LinkedList, HashMap span two generations?
>>>
>>> For example, I initialize some data structures as follows.
>>>
>>> Say, hashMap = {str1: obj1; str2: obj2; ...; strn: objn;}
>>>
>>> The object body of hashMap is in the same generation, including the data
>>> structure containing references of str(i) and obj(i); however, the object
>>> bodies of str(i) and obj(i) may span different generations.
>>>
>>> BTW, hashMap itself (not its referenced object body) is a reference and,
>>> hence, on stack (not on java heap) since it's a local variable.
>>>
>>> Hope this helps build a concrete picture of memory layout.
>>>
>>>
>>>
>>> --------------------------------------------------------------------------------------------------
>>>
>>> *import* java.util.ArrayList;
>>>
>>> *import* java.util.HashMap;
>>>
>>> *import* java.util.LinkedList;
>>>
>>> *import* java.util.List;
>>>
>>> *import* java.util.Map;
>>>
>>>
>>>
>>> *public* *class* ObjectTest {
>>>
>>>      *public* *static* *void* main(String[] args) {
>>>
>>>         List<Obj> arrayList = *new* ArrayList<Obj>();
>>>
>>>         List<Obj> linkedList = *new* LinkedList<Obj>();
>>>
>>>         Map<String, Obj> hashMap = *new* HashMap<String, Obj>();
>>>
>>>
>>>
>>>         *for*(*int* i = 0; i < 10000; i++) {
>>>
>>>             Obj arrayObj = *new* Obj();
>>>
>>>             arrayList.add(arrayObj);
>>>
>>>         }
>>>
>>>
>>>
>>>         *for*(*int* i = 0; i < 10000; i++) {
>>>
>>>             Obj linkedObj = *new* Obj();
>>>
>>>             linkedList.add(linkedObj);
>>>
>>>         }
>>>
>>>
>>>
>>>         *for*(*int* i = 0; i < 10000; i++) {
>>>
>>>             String str = i + "";
>>>
>>>             Obj hashObj = *new* Obj();
>>>
>>>             hashMap.put(str, hashObj);
>>>
>>>         }
>>>
>>>      }
>>>
>>> }
>>>
>>>
>>>
>>> *class* Obj {
>>>
>>>      *byte*[] bytes;
>>>
>>>      *public* Obj() {
>>>
>>>         bytes = *new* *byte*[16];
>>>
>>>      }
>>>
>>>   }
>>>
>>>
>>> --------------------------------------------------------------------------------------------------
>>>
>>> If new gen cannot hold all the objects, GC will occur. I want to know if
>>> all the items in the data structure are copied into old gen.
>>>
>>> For example, arrayList itself exists in old while some of its arrayObjs
>>> exist in new gen. A arrayObj exists in old gen while its bytes exists in
>>> new gen.
>>>
>>>
>>>
>>>



More information about the hotspot-gc-dev mailing list