You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by Knut Anders Hatlen <Kn...@Sun.COM> on 2007/02/23 16:21:01 UTC

Nulling out variables for GC (was: Re: svn commit: r510963 ...)

djd@apache.org writes:

>  		if ((pageData == null) || (pageData.length != pageSize)) 
>          {
> +            // Give a chance for gc to release the old buffer
> +            pageData = null; 
>  			pageData = new byte[pageSize];

Out of curiosity (I have seen similar code changes go in before), why
does pageData need to be set to null to be garbage collected? Is this
a workaround for a bug on a certain JVM? If so, it would be good to
document it in a comment.

-- 
Knut Anders

Re: Nulling out variables for GC

Posted by Knut Anders Hatlen <Kn...@Sun.COM>.
Bryan Pendleton <bp...@amberpoint.com> writes:

>> in the datatype code for a binary object, the value may change from
>> a 30Mb array to a 2 byte array, so nulling out the reference before
>> creating a new one is good. 
>
> Is there any value to explicitly calling System.gc() in a situation
> such as this?

I don't think so. The JVM should be clever enough to start a GC on its
own if it doesn't have enough memory. But you never know... :) By
calling System.gc() explicitly, you will start a GC regardless of the
need for a GC, so it might cost more than you win.

I have seen calls to System.gc() and System.runFinalization() some
places in the code. I don't think those calls are there primarily to
reclaim space, but to make sure (or more accurately: increase the
probability) that the finalizers for unreferenced objects have been
run so that they release whichever resources they may be holding.

-- 
Knut Anders

Re: Nulling out variables for GC

Posted by Bryan Pendleton <bp...@amberpoint.com>.
> in the datatype code for a binary object, the value may change from a 
> 30Mb array to a 2 byte array, so nulling out the reference before 
> creating a new one is good. 

Is there any value to explicitly calling System.gc() in a situation
such as this?

thanks,

bryan


Re: Nulling out variables for GC

Posted by Daniel John Debrunner <dj...@apache.org>.
Knut Anders Hatlen wrote:
> Daniel John Debrunner <dj...@apache.org> writes:
> 
>> Knut Anders Hatlen wrote:
>>> djd@apache.org writes:
>>>
>>>>  		if ((pageData == null) || (pageData.length !=
>>>> pageSize))          {
>>>> +            // Give a chance for gc to release the old buffer
>>>> +            pageData = null;  			pageData = new
>>>> byte[pageSize];
>>> Out of curiosity (I have seen similar code changes go in before), why
>>> does pageData need to be set to null to be garbage collected? Is this
>>> a workaround for a bug on a certain JVM? If so, it would be good to
>>> document it in a comment.
>> So the idea is to allow the old value of pageData garbage collected
>> before the allocation of the new array, rather than after.
>> Here's the thinking ...
>>
>> Say on entry pageData is a reference to an 8k array, but the code
>> needs a 16k array. With pageData = new byte[16384] I believe the
>> semantics of Java require the non-atomic ordering be:
>>
>>      allocate 16k array
>>      set the field pageData to the newly allocated buffer.
>>
>> Thus that order requires that the code at some point has a reference
>> to both arrays and thus the 8k array cannot be garbage collected until
>> after the field is set. I believe this to be the case because if the
>> new byte[16384] throws OutOfMemoryError then pageData must remain set
>> to the old value (8k array).
>>
>> So (in an extreme case) if the vm only had 10k of free memory the
>> allocation would fail, but if pageData is nulled out before the new
>> then the free memory can jump to 18k and the allocation succeed.
>>
>> So maybe this is incorrect thinking?
>> Do the JVM's have some special optimizations to not require this?
> 
> Hmm, that's interesting. A small test case indicated that you're
> right. Thanks for clearing it up!
> 
> Perhaps the comment could be more verbose? I think it would be better
> if it said that it gave gc a chance to release the old buffer before
> it allocates the new buffer. It's a bit confusing as it stands now (to
> me at least), since gc does have a chance to release the buffer if the
> next statement doesn't fail.

Will do. I also think that this should *not* be a general coding style, 
  just selective where the object to be gc'ed may be large. For example 
in the datatype code for a binary object, the value may change from a 
30Mb array to a 2 byte array, so nulling out the reference before 
creating a new one is good. Also I don't know what happens if the 
variable is one that would go out of scope if an exception was thrown, 
because in that situation the jvm could remove the reference to the old 
object before it tries to allocate the new object.


Dan.



Re: Nulling out variables for GC

Posted by Knut Anders Hatlen <Kn...@Sun.COM>.
Daniel John Debrunner <dj...@apache.org> writes:

> Knut Anders Hatlen wrote:
>> djd@apache.org writes:
>>
>>>  		if ((pageData == null) || (pageData.length !=
>>> pageSize))          {
>>> +            // Give a chance for gc to release the old buffer
>>> +            pageData = null;  			pageData = new
>>> byte[pageSize];
>>
>> Out of curiosity (I have seen similar code changes go in before), why
>> does pageData need to be set to null to be garbage collected? Is this
>> a workaround for a bug on a certain JVM? If so, it would be good to
>> document it in a comment.
>
> So the idea is to allow the old value of pageData garbage collected
> before the allocation of the new array, rather than after.
> Here's the thinking ...
>
> Say on entry pageData is a reference to an 8k array, but the code
> needs a 16k array. With pageData = new byte[16384] I believe the
> semantics of Java require the non-atomic ordering be:
>
>      allocate 16k array
>      set the field pageData to the newly allocated buffer.
>
> Thus that order requires that the code at some point has a reference
> to both arrays and thus the 8k array cannot be garbage collected until
> after the field is set. I believe this to be the case because if the
> new byte[16384] throws OutOfMemoryError then pageData must remain set
> to the old value (8k array).
>
> So (in an extreme case) if the vm only had 10k of free memory the
> allocation would fail, but if pageData is nulled out before the new
> then the free memory can jump to 18k and the allocation succeed.
>
> So maybe this is incorrect thinking?
> Do the JVM's have some special optimizations to not require this?

Hmm, that's interesting. A small test case indicated that you're
right. Thanks for clearing it up!

Perhaps the comment could be more verbose? I think it would be better
if it said that it gave gc a chance to release the old buffer before
it allocates the new buffer. It's a bit confusing as it stands now (to
me at least), since gc does have a chance to release the buffer if the
next statement doesn't fail.

-- 
Knut Anders

Re: Nulling out variables for GC

Posted by Daniel John Debrunner <dj...@apache.org>.
Knut Anders Hatlen wrote:
> djd@apache.org writes:
> 
>>  		if ((pageData == null) || (pageData.length != pageSize)) 
>>          {
>> +            // Give a chance for gc to release the old buffer
>> +            pageData = null; 
>>  			pageData = new byte[pageSize];
> 
> Out of curiosity (I have seen similar code changes go in before), why
> does pageData need to be set to null to be garbage collected? Is this
> a workaround for a bug on a certain JVM? If so, it would be good to
> document it in a comment.

So the idea is to allow the old value of pageData garbage collected 
before the allocation of the new array, rather than after.
Here's the thinking ...

Say on entry pageData is a reference to an 8k array, but the code needs 
a 16k array. With pageData = new byte[16384] I believe the semantics of 
Java require the non-atomic ordering be:

      allocate 16k array
      set the field pageData to the newly allocated buffer.

Thus that order requires that the code at some point has a reference to 
both arrays and thus the 8k array cannot be garbage collected until 
after the field is set. I believe this to be the case because if the new 
byte[16384] throws OutOfMemoryError then pageData must remain set to the 
old value (8k array).

So (in an extreme case) if the vm only had 10k of free memory the 
allocation would fail, but if pageData is nulled out before the new then 
the free memory can jump to 18k and the allocation succeed.

So maybe this is incorrect thinking?
Do the JVM's have some special optimizations to not require this?

Dan.