how many objects r eligible for garbage Collection ?

A

Andreas Leitgeb

Mark Thornton said:
Java 6 does collect objects where the only references have no further
use. It is possible to observe this behaviour if you also have a weak
reference to the 'garbage'.

I did a small experiment (though only with some late beta of 1.6)
and compiled this class:

class X {
void foo() {
X x=new X();
X y=new X();
}
}
and javap showed, that these two objects are each stored in
some local var (astore_1&2), rather than just "pop"ed from stack,
as I would have expected, for compilers that really saw that
variable x is no longer used....

But then again, it might just as well be an optimization inside
the JVM, not in the compiler itself.
 
N

Naveen Kumar

End of the day.. how many accept that there are two objects available
for GC and how many for only 1 object available for GC ??

Which is the correct answer and how ?

Guess it has confused to lot many other experts too, like how it had
confused me :).
 
L

Lew

Naveen said:
End of the day.. how many accept that there are two objects available
for GC and how many for only 1 object available for GC ??

Which is the correct answer and how ?

Guess it has confused to lot many other experts too, like how it had
confused me :).

Lew suggested:
Here's how to solve this one: Identify all the object references in the program at that point.
(Is 'story' one of them?) See which objects /used to have/ references but no longer do.
Those are the ones eligible for GC.
It might help to write down for each line of code which objects exist,
and which ones from previous lines no longer have references to them.
Follow the whole chain - if an object holds a reference to another object,
there's another object to track.

Let's try that.
when //do stuff is reached How many Objects are eligible for garbage Collection ?

class Card {
Short story=5;
Card go(Card c)
{
c=null;
return c;
}

public static void main(String[] args)
{
Card c1=new Card();
// c1 -> a Card #1. c1.story -> a Short #2.

Card c2=new Card();
// c2 -> a Card #3. c2.story -> a Short #4.

Card c3=c1.go(c2);
// c3 == null - no objects created.

c1=null;
// Card #1 is unreachable. Short #2 is unreachable.

//do stuff;
// depending on whether c2 is used later, it may be GC-eligible.
// releasing the object pointed to by c2 would release #3 and #4.
}
}
 
P

Patricia Shanahan

Naveen said:
End of the day.. how many accept that there are two objects available
for GC and how many for only 1 object available for GC ??

Can you clarify what "//do stuff" does? Does it reference c2?

Patricia
 
A

Andreas Leitgeb

Naveen Kumar said:
End of the day.. how many accept that there are two objects available
for GC and how many for only 1 object available for GC ??
Which is the correct answer and how ?

It is even possible, that upon reaching the "// do stuff" part
*no* object at all is eligible for GC !


Gubfr bowrpgf znl unir orra nflapuebabhfyl TP'q whfg n pch-plpyr
orsber gur cbvag jr'er ybbxvat ng :) (rot13 for spoiler)
 
R

Roger Lindsjö

Mark said:
Java 6 does collect objects where the only references have no further
use. It is possible to observe this behaviour if you also have a weak
reference to the 'garbage'.

I did not know that it was implemented for Java 6. Will write a sscce to
show this.

//Roger Lindsjö
 
R

Roger Lindsjö

Roger said:
I did not know that it was implemented for Java 6. Will write a sscce to
show this.

I did not manage to observe this, perhaps my program is flawed. I'm
running on:
java version "1.6.0_04"
Java(TM) SE Runtime Environment (build 1.6.0_04-b12)
Java HotSpot(TM) Server VM (build 10.0-b19, mixed mode)

<sscce>
import java.util.WeakHashMap;

public class GcExample {

private WeakHashMap<Object, Object> map =
new WeakHashMap<Object, Object>();

public static void main(String... args) throws Exception {
GcExample g = new GcExample();
g.add(false, false, false);
g.add(false, false, true);
g.add(false, true, false);
g.add(false, true, true);
g.add(true, false, false);
g.add(true, false, true);
g.add(true, true, false);
g.add(true, true, true);
}

public void add(boolean nullify, boolean gc, boolean sleep)
throws Exception {
int garbageLoops = 0;
try {
Object key = new Object();
map.put(key, new byte[20000]);
if (nullify) {
key = null;
}
if (gc) {
System.gc();
}
if (sleep) {
Thread.sleep(100);
}
// Generate garbage
while (map.size() > 0) {
byte[] b = new byte[1000000 * (garbageLoops + 1)];
garbageLoops++;
}
} catch (OutOfMemoryError e) {
} finally {
System.out.format(
"Pass:%-5b Nullify:%-5b GC:%-5b Sleep:%-5b GC factor:%d%n",
map.size() == 0, nullify, gc, sleep, garbageLoops);
map.clear();
}
}
}
</sscce>

java -Xmx32m -Xms32m GcExample
Pass:false Nullify:false GC:false Sleep:false GC factor:29
Pass:false Nullify:false GC:false Sleep:true GC factor:29
Pass:false Nullify:false GC:true Sleep:false GC factor:29
Pass:false Nullify:false GC:true Sleep:true GC factor:29
Pass:true Nullify:true GC:false Sleep:false GC factor:8
Pass:true Nullify:true GC:false Sleep:true GC factor:7
Pass:true Nullify:true GC:true Sleep:false GC factor:1
Pass:true Nullify:true GC:true Sleep:true GC factor:0

taskset -c 0 java -Xmx32m -Xms32m GcExample
Pass:false Nullify:false GC:false Sleep:false GC factor:29
Pass:false Nullify:false GC:false Sleep:true GC factor:29
Pass:false Nullify:false GC:true Sleep:false GC factor:29
Pass:false Nullify:false GC:true Sleep:true GC factor:29
Pass:true Nullify:true GC:false Sleep:false GC factor:8
Pass:true Nullify:true GC:false Sleep:true GC factor:7
Pass:true Nullify:true GC:true Sleep:false GC factor:0
Pass:true Nullify:true GC:true Sleep:true GC factor:0
 
L

Lew

Andreas said:
It is even possible, that upon reaching the "// do stuff" part
*no* object at all is eligible for GC !

That is clearly not correct for the given example.
 
L

Lew

Roger said:
Roger said:
I did not know that it was implemented for Java 6. Will write a sscce
to show this.

I did not manage to observe this, perhaps my program is flawed. I'm
running on:
java version "1.6.0_04"
Java(TM) SE Runtime Environment (build 1.6.0_04-b12)
Java HotSpot(TM) Server VM (build 10.0-b19, mixed mode)

<sscce>
import java.util.WeakHashMap;

public class GcExample {

private WeakHashMap<Object, Object> map =
new WeakHashMap<Object, Object>();

public static void main(String... args) throws Exception {
GcExample g = new GcExample();
g.add(false, false, false);
g.add(false, false, true);
g.add(false, true, false);
g.add(false, true, true);
g.add(true, false, false);
g.add(true, false, true);
g.add(true, true, false);
g.add(true, true, true);
}

public void add(boolean nullify, boolean gc, boolean sleep)
throws Exception {
int garbageLoops = 0;
try {
Object key = new Object();
map.put(key, new byte[20000]);
if (nullify) {
key = null;
}
if (gc) {
System.gc();
}
if (sleep) {
Thread.sleep(100);
}
// Generate garbage
while (map.size() > 0) {
byte[] b = new byte[1000000 * (garbageLoops + 1)];
garbageLoops++;
}
} catch (OutOfMemoryError e) {
} finally {
System.out.format(
"Pass:%-5b Nullify:%-5b GC:%-5b Sleep:%-5b GC factor:%d%n",
map.size() == 0, nullify, gc, sleep, garbageLoops);
map.clear();
}
}
}
</sscce>

How does this demonstrate that objects are or are not collected after they go
out of use?

The System.gc() call is going to invoke major collections, if any, and there's
no guarantee of that. We don't know if the reference analyzer works on
objects that have been tenured, or if suggested GCs interfere with the
heuristics. OK, you might know, but I don't and there aren't any comments
about that in the example.

The loop around the byte [] allocation only leaves one array to test at the
end of the loop - all the arrays allocated in all but the last iteration are
eligible for GC by virture of not having a reference any more, which is not
the behavior under test. The method ends just after the last iteration, so
everything in the method is immediately available for GC at method return anyway.

A good optimizer might eliminate the allocation of 'b' at run time since the
array is not used.

You don't put any pressure on the heap to force weak references to go away.

The averred scenario, that an object will potentially be collected when there
is a reference to it but that reference is no longer used, is not represented
in the example that I can see.

I do not understand your metrics, or what you mean by calling the number of
"allocate-and-discard" loops a "GC factor".

I have no idea what your example demonstrates, except for that it is clear
that something does get collected.

Would you please explain the example and how it is designed to demonstrate
what it purports to demonstrate? For that matter, please explain what it
purports to demonstrate.
 
R

Roger Lindsjö

Lew said:
Roger said:
Roger said:
Mark Thornton wrote:
Roger Lindsjö wrote:

The Card object references by c2 might be available too, depending
on what "// do stuff" does with it. Many (all?) GC implementations
seem to not collect objects referenced by variables still on the
stack, but I don't think they are forced to.


Java 6 does collect objects where the only references have no
further use. It is possible to observe this behaviour if you also
have a weak reference to the 'garbage'.

I did not know that it was implemented for Java 6. Will write a sscce
to show this.

I did not manage to observe this, perhaps my program is flawed. I'm
running on:
java version "1.6.0_04"
Java(TM) SE Runtime Environment (build 1.6.0_04-b12)
Java HotSpot(TM) Server VM (build 10.0-b19, mixed mode)

<sscce>
import java.util.WeakHashMap;

public class GcExample {

private WeakHashMap<Object, Object> map =
new WeakHashMap<Object, Object>();

public static void main(String... args) throws Exception {
GcExample g = new GcExample();
g.add(false, false, false);
g.add(false, false, true);
g.add(false, true, false);
g.add(false, true, true);
g.add(true, false, false);
g.add(true, false, true);
g.add(true, true, false);
g.add(true, true, true);
}

public void add(boolean nullify, boolean gc, boolean sleep)
throws Exception {
int garbageLoops = 0;
try {
Object key = new Object();
map.put(key, new byte[20000]);
if (nullify) {
key = null;
}
if (gc) {
System.gc();
}
if (sleep) {
Thread.sleep(100);
}
// Generate garbage
while (map.size() > 0) {
byte[] b = new byte[1000000 * (garbageLoops + 1)];
garbageLoops++;
}
} catch (OutOfMemoryError e) {
} finally {
System.out.format(
"Pass:%-5b Nullify:%-5b GC:%-5b Sleep:%-5b GC factor:%d%n",
map.size() == 0, nullify, gc, sleep, garbageLoops);
map.clear();
}
}
}
</sscce>

How does this demonstrate that objects are or are not collected after
they go out of use?

The System.gc() call is going to invoke major collections, if any, and
there's no guarantee of that. We don't know if the reference analyzer
works on objects that have been tenured, or if suggested GCs interfere
with the heuristics. OK, you might know, but I don't and there aren't
any comments about that in the example.

I'm quite aware of what System.gc() does, what I tried to establis was
if calling it or not would make any difference to my program. If you
look closely you will see that I have three different options that could
be executed or skipped. They are:
1. Explicitly nulling the reference to the key object.
2. Requesting a GC.
3. Waiting a short while.
I also try running through all permutations of these options (the sleep
which I first tried on a whim made different results on my machine
depending on if I limited the JVM to one CPU or not).
The loop around the byte [] allocation only leaves one array to test at
the end of the loop - all the arrays allocated in all but the last
iteration are eligible for GC by virture of not having a reference any
more, which is not the behavior under test. The method ends just after
the last iteration, so everything in the method is immediately available
for GC at method return anyway.

A good optimizer might eliminate the allocation of 'b' at run time since
the array is not used.

Yes it could, but my testing indicated that it did not. Would be
interesting to see if it would still generate the "OutOfMemoryException"
though.
You don't put any pressure on the heap to force weak references to go away.

But they do go away, as long as there is no local reference to the key.
And I made an other application which kept the arrays and used them for
some silly calculations, but that code made no difference, so I removed
it to make the sscce shorter.
The averred scenario, that an object will potentially be collected when
there is a reference to it but that reference is no longer used, is not
represented in the example that I can see.

As far as I understand, a SoftHashMap will allow the referenced object
be collected IFF there are no references to the key.

Object key = new Object();
map.put(key, new DummyObject());
// more code
if the "more code" part does not use "key", then the dummy object would
be available for collection. That's what Mark Thornton wrote Java 6
would be able to do.
I do not understand your metrics, or what you mean by calling the number
of "allocate-and-discard" loops a "GC factor".

Sorry about that, the original code showed the size of the largest
allocated object as a ratio to the first allocated object. Rewrote the
code to instead use a counter but forgot to update the output.
I have no idea what your example demonstrates, except for that it is
clear that something does get collected.

Specifically, the object referenced by the SoftHashMap, but only if I
set key to null (or any other object not being used as a key in the map
I would guess).
Would you please explain the example and how it is designed to
demonstrate what it purports to demonstrate? For that matter, please
explain what it purports to demonstrate.

The idea was to show that objects would be collected even if references
as long as the reference would not be used any more. Sadly, that did not
work which is indicated by my first comment "I did not manage to observe
this, perhaps my program is flawed".

In the example below I use WeakHashMap which references a large int[]. I
then allocate fairly small objects until either the map releases the
large object or an OutOfMemoryError is generated. The goal is to get the
map to have a size 0 which would have shown that the object referenced
by key was collected wile key was in scope but unreachable. Sadly, this
example does not prove Mark Thornton right either. Manually setting the
key to null before the garbage generating loop will allow the large
int[] to be collected;

<sscce>
import java.util.LinkedList;
import java.util.List;
import java.util.WeakHashMap;

public class GcExample {

private WeakHashMap<Object,int[]> map =
new WeakHashMap<Object,int[]>();

public static void main(String... args) throws Exception {
new GcExample().run();
}

public void run() {
List<int[]> garbage = new LinkedList<int[]>();
try {
Object key = new Object();
map.put(key, new int[5000000]);
// Generate garbage to force key and large int[] to
// be collected.
while (map.size() > 0) {
garbage.add(new int[2000]);
}
} catch (OutOfMemoryError e) {
}
System.out.format("Large int[] collected: %b. Allocations %d%n",
map.size() == 0, garbage.size());
}
}
</sscce>

//Roger Lindsjö
 
L

Lew

Andreas said:
Did or didn't you read the spoiler?

I confess, I must have not read the spoiler, as I do not know what is the
spoiler. That is all right. I would be delighted to learn how there may be
no objects eligible for GC. GC is a mysterious subject whose depths I've
barely skimmed, much less plumbed, and I am finding out new things always
about it.
 
A

Andreas Leitgeb

Lew said:
I confess, I must have not read the spoiler, ...

The spoiler (^L'ed and rot13'ed) was, that at the very
point of where we're looking at unreachable objects, all
those objects that have become eligible in the lines before
may already have been (asynchronously) GC'd, and in this
case these objects are of course no longer there, and as
such no longer "eligible". :)

While it's beside the original point, I find it a
plausibly possible scenario for the given example.
 
L

Lew

Andreas said:
The spoiler (^L'ed and rot13'ed) was, that at the very

This is some kind of poetry? Should I have seen the post to which you are
referring? Were you the poster?
point of where we're looking at unreachable objects, all
those objects that have become eligible in the lines before
may already have been (asynchronously) GC'd, and in this
case these objects are of course no longer there, and as
such no longer "eligible". :)

While it's beside the original point, I find it a
plausibly possible scenario for the given example.

I do not find this beside the original point at all. It is very relevant and
you raise an excellent point. Good catch.
 
A

Andreas Leitgeb

Lew said:
This is some kind of poetry? Should I have seen the post to which you are
referring? Were you the poster?

I was speaking of article <[email protected]>
My intent was to keep others in suspense a bit, before explaing my
not too serious point about "possibly no objects being eligible for
GC at a particular point".

Most newsclients (of those I've yet seen) seem to interpret a
Ascii-formfeed character (aka ^L, or \v, or \013) such that they
do hide away the text that follows until some key is pressed.

Google-groups doesn't do this, so I also encoded the text with
"rot13" (google for it, if you want to know about it), which I
considered also quite common in usenet. Many readers have some
feature to toggle "rot13"-encoding of the article on some
keystroke, so it's not much of a burden with those.

I don't understand, how "poetry" enters the game.
It wasn't even in rhymes...

When you disagreed with my point, I wasn't sure, whether you
had missed that explanation (the "spoiler"), or whether you
were one step further and had spotted any flaw in it.
As it seems, it was the former.
I do not find this beside the original point at all.
It is very relevant and you raise an excellent point.
Good catch.

In a discussion of eligibility for GC, the possibility
of GC having happened already is IMO entirely uninteresting,
despite it's possibility.

If instead the question had been: "why isn't the finalizer
for this object called *at or after* this particular point?",
then the same would have been much more of a useful and serious
answer :)
 
L

Lew

Andreas said:
I was speaking of article <[email protected]>

I realize I am being obtuse, and I truly apologize, but you are losing me six
ways from Sunday. The URI you post, my newsreader interprets as an email
address and opens a new email to that address when I click on it. I know what
rot13 is, I just hadn't seen anything in that format. I am missing antecedents.
Most newsclients (of those I've yet seen) seem to interpret a
Ascii-formfeed character (aka ^L, or \v, or \013) such that they
do hide away the text that follows until some key is pressed.

I saw no post with either a formfeed nor rot13 "encoded" text.
Google-groups doesn't do this, so I also encoded the text with
"rot13" (google for it, if you want to know about it), which I
considered also quite common in usenet. Many readers have some
feature to toggle "rot13"-encoding of the article on some
keystroke, so it's not much of a burden with those.

I just haven't seen any rot13 text to decode, is the problem.
I don't understand, how "poetry" enters the game.
It wasn't even in rhymes...

What does rhyme have to do with poetry?

Poetry is the use of language for purely evocative purpose. When I see
statements that do not parse well as prose, I try the "poetry" template on it.
In the case of my question, you referenced ^L and rot13, and I had seen
neither elsewhere in the thread. My question was rhetorical, designed to
illustrate the degree of confusion I feel. The "poetry" would have been in
the metaphorical "clearing" of my mental screen and "scrambling" of the sense
of things, represented by your citations of ^L and rot13. Absent any tangible
antecedent, I hypothesized that you were reveling in metaphor.
When you disagreed with my point, I wasn't sure, whether you
had missed that explanation (the "spoiler"), or whether you
were one step further and had spotted any flaw in it.
As it seems, it was the former.

I have yet to find this "spoiler" to which you keep referring.

Now that I understand your answer, that no objects may be eligible for
collection at the given point, I find it cogent.

As I stated:
Andreas:
In a discussion of eligibility for GC, the possibility
of GC having happened already is IMO entirely uninteresting,
despite it's possibility.

Just so. My original "disagreement" with your analysis had to do with how I
interpreted the pedagogical conditions of when '// do stuff' happens. You
allowed a finite interval between the dereferencing of the first Card and the
breakpoint. I interpreted it as "at time epsilon after the dereferencing such
that no intervening GC could have occurred." I would call the scenario of GC
having already occurred between dereference and the breakpoint as the
degenerate case. Clearly the intent of the question was to reason about the
state under the assumption of no intervening GC activity.

However, I had not even considered the degenerate case until you brought it
up. Now I distinguish the pedagogical scenario, when we may assume no
intervening GC, from the real world, where I'd bloody well better consider the
possibility.

Thanks to you.
If instead the question had been: "why isn't the finalizer
for this object called *at or after* this particular point?",
then the same would have been much more of a useful and serious
answer :)

Now you've involved finalizers, which if non-trivial induce at least a second
GC cycle before an object can be truly collected, and could emergently prevent
complete collection altogether. Trivial finalizers (i.e., unchanged from that
inherited from Object) are never called.

Having to account for that in the answer does, indeed, make it more serious,
and for certain things more useful. However, the question of GC /per se/ is
more generally applicable and relevant even when finalizers are not at issue.
 
L

Lew

Lew said:
I realize I am being obtuse, and I truly apologize, but you are losing
me six ways from Sunday. The URI you post, my newsreader interprets
as an email address and opens a new email to that address when I click

Mystery solved.

The rot13 part of that post got completely by me because the ^L hid it to
where I didn't realize there was more to see. The attempt to hide the spoiler
hid that there was anything to find, so I didn't look.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top