do self references cause memory leaks in Java?

N

Novice

Hi, I am doing some work with Java and C++ and am curious as to whether self
references in Java cause memory leaks.

For example:

class Test{
Object foo =this;
}

If I instantiate Test, the reference count of any Test object will never
become zero (as it always keeps a reference to itself) so long as the foo
variable is never re-assigned.

Does this present a problem for Java's garbage collection?

Thanks,
Novice
 
A

Adam Maass

Novice said:
Hi, I am doing some work with Java and C++ and am curious as to whether self
references in Java cause memory leaks.

For example:

class Test{
Object foo =this;
}

If I instantiate Test, the reference count of any Test object will never
become zero (as it always keeps a reference to itself) so long as the foo
variable is never re-assigned.

Does this present a problem for Java's garbage collection?

Garbage collection in Java does not use reference counting. Rather, most
simple gc systems use a mark-and-sweep method.

-- Adam Maass
 
N

Novice

|
| > Hi, I am doing some work with Java and C++ and am curious as to whether
| self
| > references in Java cause memory leaks.
| >
| > For example:
| >
| > class Test{
| > Object foo =this;
| > }
| >
| > If I instantiate Test, the reference count of any Test object will never
| > become zero (as it always keeps a reference to itself) so long as the
foo
| > variable is never re-assigned.
| >
| > Does this present a problem for Java's garbage collection?
| >
|
| Garbage collection in Java does not use reference counting. Rather, most
| simple gc systems use a mark-and-sweep method.
|

Is there somewhere I can find this documented?

The impression I get from the very high level documents I've read on
java.sun.com's website is:
"The Java runtime environment has a garbage collector that periodically
frees the memory used by objects that are no longer referenced."

So if an object references itself and never stops referencing itself that
object will always have at least one reference.

Thanks,
Novice
 
N

Novice

In fact I found this article:
http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html

on the sun website and it says that:
"Circular strong references don't necessarily cause memory leaks."

This statement doesn't seem to indicate that all objects which are no longer
referenced (except by themselves) will be removed/deleted.

In fact, it goes on further to say:
"although the VM might not actually collect these objects for an indefinite
amount of time"

Which to me says that the VM may not remove/delete these objects from memory
until the VM is shut-down.

Is there any reason to believe otherwise?

Thanks,
Novice
 
N

Novice

|
| The VM might not collect any object for an indefinite amount of time. So
yes,
| uncollected objects may remain in memory until the VM is shut down.
|

This to me is a problem - I mean server programs would eventually run out of
memory if they made use of classes with circular dependencies...

Can anyone provide any clarification on this?

Or do most people know to try to avoid circular dependencies?

Thanks,
Novice
 
A

Adam Maass

Novice said:
|
| > Hi, I am doing some work with Java and C++ and am curious as to whether
| self
| > references in Java cause memory leaks.
| >
| > For example:
| >
| > class Test{
| > Object foo =this;
| > }
| >
| > If I instantiate Test, the reference count of any Test object will never
| > become zero (as it always keeps a reference to itself) so long as the
foo
| > variable is never re-assigned.
| >
| > Does this present a problem for Java's garbage collection?
| >
|
| Garbage collection in Java does not use reference counting. Rather, most
| simple gc systems use a mark-and-sweep method.
|

Is there somewhere I can find this documented?

OK, this isn't exactly crystal-clear from the specs, but here's the
definition of an object's lifecycle:

http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#74701

And here's the definition of the term "reachable," which is part of the
lifecycle definition:

http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44762


The short answer is that an object that refers to itself may be garbage
collected if there are no references to it from any live thread.

Java garbage collection does not use (a naive implementation of)
reference-counting.



-- Adam Maass
 
B

Bent C Dalager

This to me is a problem - I mean server programs would eventually run out of
memory if they made use of classes with circular dependencies...

The VM will always do garbage collection - and a complete garbage
collection if necessary - before reporting an out of memory condition.

The case of not having had anything collected until program shutdown
will only occur for programs that did not run out of memory during
execution.
Can anyone provide any clarification on this?

Or do most people know to try to avoid circular dependencies?

Circular dependencies aren't a problem. If you're using an
experimental VM, of course, you might want to make a point out of
checking its documentation on this point.

I believe some older VMs did conservative GC, which is a bit of a
mess.

Cheers
Bent D
 
P

Phillip Lord

Novice> | The VM might not collect any object for an indefinite
Novice> amount of |time. So yes, uncollected objects may remain in
Novice> memory until the VM is shut |down.
Novice> |

Novice> This to me is a problem - I mean server programs would
Novice> eventually run out of memory if they made use of classes
Novice> with circular dependencies...

Novice> Can anyone provide any clarification on this?

Novice> Or do most people know to try to avoid circular
Novice> dependencies?


No. The JVM does not have to collect objects until it feels it wants
to. Maybe never.

However it is required to free all available memory before it throws
an out of memory error.

So, for instance, a JVM might choose not to GC until it runs short of
memory. This makes sense, as GC is expensive. Why do it if you don't
need to. If you are running out of memory, of course, this is a
different issue. Then you do need to.

In short, don't worry about circular dependencies. They will not cause
the GC problems. And generally don't worry about when objects that are
our of scope, are actually GC'd. Its an implementation issue, and it
will differ between JVM's.

Cheers

Phil
 
I

Ian deSouza

I think it might be worthwhile talking about the mark-and-sweep GC
that you had previously mentioned. Mark-and-sweep involves the GC
first looking at the main program and looking for object references
there, and "marking" them as valid. It then looks at the references
that those hold, marking them, and so on.

After it completes the marking, it then deletes the objects that
weren't marked, (since it has has a complete list of all the new'ed
objects), first calling finalize on the objects before removing the
memory.

Mark-and-sweep been in place since at least 1.1 (maybe before)..
 
D

Doug Pardee

Steve Horsley said:
A full Garbage Collection will only run when the VM doesn't have enough
memory to create a new Object when required. A short-lived program or a
program that dives into a tight loop without creating and discarding many
objects may never trigger a full GC.

This is only true for certain environments.

The JVM specification declares that the behavior of the garbage
collector is not defined, and the JVM implementor has a free hand. The
only requirements are that there be a garbage collector, and that it
make its best effort to reclaim memory before throwing the
OutOfMemoryError.

Most of us are using Sun JVMs, and Sun has documented their GCs fairly
well. It's worth the trip to the Sun Web site to read the facts,
rather than relying on conjecture.

Modern Sun JVMs use multiple heaps, with separate garbage collectors
on each. These typically DO run on an as-needed basis, but in many
cases a "full GC" is never triggered even in a program that creates
and discards many objects.

On the other hand, if you're using RMI, the Distributed Garbage
Collector will force a "full GC" on a regular basis. By default, the
DGC triggers a full garbage collection every 60 seconds.
This is why finalize() cannot be
relied on to clean up resources - the program may terminate normally
without the finalizers ever running.

Again, not *necessarily* true. It is true for the default situation,
but if you call System.runFinalizersOnExit(true) at some point, the
finalizers will always be executed. Heh... unless someone calls
System.runFinalizersOnExit(false) after you've called it with "true"
:)
 
D

Doug Pardee

I think it might be worthwhile talking about the mark-and-sweep GC
that you had previously mentioned.
[snip]
Mark-and-sweep been in place since at least 1.1 (maybe before)..

Historically, Sun JVMs have not used mark-and-sweep GCs.

The older Sun JVMs used mark-and-compact. The difference is that
mark-and-sweep leaves a checkerboarded heap.

Modern Sun JVMs (since 1.2.something) use multiple heaps, divided into
two generations for user objects and a third generation for system
objects. The two user generations use separate garbage collectors. The
young generation uses a single-pass "copying" garbage collector: all
live objects are copied from Eden and the current survivor space into
the new survivor space and possibly the tenured generation, and then
Eden and the current survivor space are declared empty, and the new
survivor space becomes the current survivor space. The tenured
generation uses mark-and-compact.

As of 1.4.1, Sun's JVMs have added some additional GC options, one of
which is a low-latency, mostly concurrent, mark-and-sweep GC for the
tenured generation. Its operation is a six-phase process that is a
*bit* more complicated than an ordinary mark-and-sweep. See the FAQ
reference below.

A couple of useful references:
http://java.sun.com/docs/hotspot/gc1.4.2/faq.html
http://java.sun.com/docs/hotspot/gc1.4.2/
 
S

S. Balk

Hi, I am doing some work with Java and C++ and am curious as to whether
self
references in Java cause memory leaks.

For example:

class Test{
Object foo =this;
}

If I instantiate Test, the reference count of any Test object will never
become zero (as it always keeps a reference to itself) so long as the foo
variable is never re-assigned.

Does this present a problem for Java's garbage collection?

why don't you stress-test this little class by generating trillions of
objects, and watch the GC-log
 
S

Steve Horsley

Again, not *necessarily* true. It is true for the default situation,
but if you call System.runFinalizersOnExit(true) at some point, the
finalizers will always be executed. Heh... unless someone calls
System.runFinalizersOnExit(false) after you've called it with "true"
:)

runFinalizerdOnExit() is deprecated as "inherently unsafe".

Steve
 
S

S. Balk

watch the GC-log
how would he to that?

by using java -verbose:gc



another way is to set the maximum amount of allocatable memory to a very low
value, for example 2MB, then create 4 million objects with references to
itself and wait for an OutOfMemoryError, although this is a quite dirty way
of testing ofcourse
 
R

Robert Olofsson

: I ran this through JProfiler (anybody want to fund me so I can buy a
: license? I'm still doing backpayments on my 20' plasma tv).

Use a free profiler instead or keep switching between optimizeit, jprobe and
jprofiler.

: class SelfReferent
: {
: Object refrerer;
: SelfReferent(Object referent)
: {
: referer = referent;
: }
: }

Ok, this code does not compile, refrerer is mispelled. So obviously this
is not the code you used.

: If I run this test, and call System.gc() manually on JProfile, there are
: still 8 allocations left on the heap (240 bytes). While this doesn't
: seem serious, it is a problem if such code is present in a long-running
: server process. This is reproducible.

If I fix your spelling error and run it with jdk/1.4.2 and my profiler, jmp,
I see that my jvm does not call GC before the test is over so I have
1000 instances of SelfReferent and 1000 instances of SelfReference.
After calling GC all of them dissapears. So my jvm does seem to handle this
case in a good way.

(to test this I added a System.in.read (); in main, after the call to test).

: So I must say that self references aren't a problem, but circular
: dependencies are.

Self references are not a problem, neither is circular references.
As someone already said, can you be sure that jprofiler-GC does a
full GC.
Also: when did you get the numbers? your test case exits very quickly so
had the GC been completed before your jvm was shut down?

/robo
 
B

Bent C Dalager

Yes. The manual states it, according to the manual they use JVMPI to
interact with the JVM. Or I might have found a 'bug' in their software. I
tried sample sizes from 10-10000; and keep getting a few left over
objects. This does not happen if I use the non-circular dependent version.

I'm not familiar with JVMPI so I'll just assume they know what they're
talking about said:
What am I doing wrong?

Nothing that I can think of.
I don't think so. The profiler keeps the VM alive after the main method
exits.

Does it do this in some mystical magical way or has it just fired up
its own non-daemon thread to keep it all ticking merrily on? If it's
magical, that might affect how things are collected (or not) I
suppose.
If I do not call gc() manually (of which I do not know how it is really
invoked, would have to check JVMPI documentation) then _all_
allocations are still visible (after the main method has finished). This
happens with both versions of the minimal test code.

When I do call the gc() method, all allocations disappear for the self
referring version and for the circular dependent one a few allocations are
still there. When I wrap the object referred to by the new call within a
SoftReference object, no allocations remain after calling the garbage
collector through the profiler.

I'm out of ideas then.
I must admit that this is not the most ideal and idealistic test at all.
Do you know by chance, how to 100% certain? TIA.

I have generally accepted that garbage collection is (apparantly)
non-deterministic and that however much I try to threaten it or yell
at it, it will still collect in its own good time. I tend to use
OptimizeIt to track down memory leaks and find my efforts constantly
frustrated by the fact that even when I have correctly unregistered
all my listeners, diposed all my windows, etc., it will still take up
to several minutes for the GC to catch on - even after hitting the
"collect" button in the profiler.

I don't really know how to get around this. Try to let the thing sit
for a couple of hours before checking on it again I suppose :)

Cheers
Bent D
 
B

Bent C Dalager

: I ran this through JProfiler (anybody want to fund me so I can buy a
: license? I'm still doing backpayments on my 20' plasma tv).

Use a free profiler instead or keep switching between optimizeit, jprobe and
jprofiler.

Are you aware of any decent free ones?
If I fix your spelling error and run it with jdk/1.4.2 and my profiler, jmp,
I see that my jvm does not call GC before the test is over so I have
1000 instances of SelfReferent and 1000 instances of SelfReference.
After calling GC all of them dissapears. So my jvm does seem to handle this
case in a good way.

Did you fix the "this"-bug in order to get circular references?

Cheers
Bent D
 
D

dhek bhun kho

(e-mail address removed) (Bent C Dalager), Thu, 17 Jul 2003 07:17:03 +0000:
Are you aware of any decent free ones?

None. Are you aware of any decent free ones? :)

Jmp? Which one is that?

Thanks for running the test case.

The JProfiler automatically starts the memory profiling while launching
the JVM. It overrides the system.exit() and keeps the main thread alive
(how I do not know, it could be an extra thread or blocking i/o). Because
gc() is not called before the VM exits, all allocations are still there
and only 'vanish'/' freed' when I hit gc() manually through the profiler.

I'm starting to think that the results I found are an artifact. I would
have to test it again on another profiler just to be sure. I'm using the
1.4.1_03 version. On the other hand : 240 bytes won't kill a server.

Greets
Bhun.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top