How memory leaks in java

A

aruna

How memory leaks in java. What are the different ways in which
memory can leak. I know of tools which eliminate the leaks,
but I want to know what causes leaks, so that I can practice
not to write a program which leaks memory?
 
R

Roedy Green

How memory leaks in java. What are the different ways in which
memory can leak. I know of tools which eliminate the leaks,
but I want to know what causes leaks, so that I can practice
not to write a program which leaks memory?

see http://mindprod.com/jgloss/packratting.html

Strictly speaking, you can't have a memory leak in Java, at least not
in the same sense you can in C++.
 
?

=?ISO-8859-1?Q?Daniel_Sj=F6blom?=

Roedy said:
see http://mindprod.com/jgloss/packratting.html

Strictly speaking, you can't have a memory leak in Java, at least not
in the same sense you can in C++.

Yes. In C++ you have memory leaks when you lose all pointers to a block
of memory and you have not yet freed the block. In java this can't
happen, because an unreachable block of memory is eligible for garbage
collection. In java you can have the reverse, where you have references
to 'dead' objects that you don't use but that still be reached from the
root set of pointers, so they can't be GCed.
 
S

Steve W. Jackson

Roedy Green said:
:On 24 Apr 2004 07:44:19 -0700, (e-mail address removed) (aruna) wrote or
:quoted :
:
:>How memory leaks in java. What are the different ways in which
:>memory can leak. I know of tools which eliminate the leaks,
:>but I want to know what causes leaks, so that I can practice
:>not to write a program which leaks memory?
:
:see http://mindprod.com/jgloss/packratting.html
:
:Strictly speaking, you can't have a memory leak in Java, at least not
:in the same sense you can in C++.

Sun would have us believe that it's "theoretically" impossible to get a
memory leak. But that's flatly not true. It can happen in complex
objects beyond just Swing components. Been there, done that. And there
are commercial tools aimed at helping find leaks so that you can resolve
them. We happen to use OptimizeIt, now sold by Borland.

The garbage collection system truly is an improvement over what C++
users have had to do, IMO. And many common references will in fact get
cleaned up. We had some concerns about whether a HashMap, ArrayList or
Vector, for instance, needed to be cleared before it would get
collected. Our testing showed that it got collected sooner if we
cleared the contents, but that it would still get collected even if we
didn't. I rather suspect that simple "circular" references, where two
objects refer to each other, but neither can be found by my code, also
get collected properly, though we weren't concerned about that (that is,
after all, one of the strengths of Java). But we fought a long, hard
battle over much more complex references eating up our memory, so we
eventually added dispose() methods in a number of our own complex
(non-GUI) classes to resolve the problem by ensuring that our references
got zapped, or caused subordinate objects to do their own dispose()
kinds of work.

The glossary reference to Threads brings up another area I stumbled
across, too. I worked for a long time trying to figure out why my
program's JWindow used at startup as a splash screen never got
collected. Then I finally discovered it was Thread related. The old
rule about quitting the JVM after all non-daemon Threads have finished
was the clue, but it took a while for me to add things up. My app's
main startup method displayed that JWindow, then built and displayed the
main app JFrame, then closed the JWindow. All attempts to call
dispose() on it, to remove its components, everything failed -- until I
realized that it left a Thread behind where my main() method was that
caused the entire problem. So now, I create the window and build it up,
but the calls to show and hide it are both done via Runnable. And it
gets collected fairly soon after! Lesson learned.

= Steve =
 
R

Roedy Green

Sun would have us believe that it's "theoretically" impossible to get a
memory leak.

read the entry at http://mindprod.com/jgloss/packratting.html

There are definitely ways you can inadvertently hold onto ram, but
that is because you have pointers to it, so you can't very well blame
Java for not being able to mindread that you will never need these
later.

A leak is where you have memory tied up with nothing pointing to it.

There are also some problems with the underlying GUI being too stupid
to do its own GC, hence the dispose kludge.
 
R

Roedy Green

So now, I create the window and build it up,
but the calls to show and hide it are both done via Runnable

I thought those had to be done from the Swing thread, or are you
creating your own new Swing thread somehow?
 
S

Steve W. Jackson

Roedy Green said:
:On Mon, 26 Apr 2004 13:52:21 -0500, "Steve W. Jackson"
:
:>Sun would have us believe that it's "theoretically" impossible to get a
:>memory leak.
:
:read the entry at http://mindprod.com/jgloss/packratting.html
:
:There are definitely ways you can inadvertently hold onto ram, but
:that is because you have pointers to it, so you can't very well blame
:Java for not being able to mindread that you will never need these
:later.
:
:A leak is where you have memory tied up with nothing pointing to it.
:
:There are also some problems with the underlying GUI being too stupid
:to do its own GC, hence the dispose kludge.
:
:
:
:--
:Canadian Mind Products, Roedy Green.
:Coaching, problem solving, economical contract programming.
:See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.

I did read that. But the simple fact is that the general belief among
those entering the Java development community is that it's not necessary
to take care of all references to objects you no longer need. That
leads people to experience memory leaks since they believe they can have
all kinds of internal references magically cleaned up for them (and also
leads some to have undeserved negative views of Java). But as your
entry points out, even Swing itself suffers from the fact that this
isn't quite true if you don't dispose components carefully.

= Steve =
 
S

Steve W. Jackson

Roedy Green said:
:On Mon, 26 Apr 2004 13:52:21 -0500, "Steve W. Jackson"
:
:> So now, I create the window and build it up,
:>but the calls to show and hide it are both done via Runnable
:
:I thought those had to be done from the Swing thread, or are you
:creating your own new Swing thread somehow?
:

There was something in the Java tutorial on Thread usage back when I was
just learning where they said it was "kinda OK" to do the main GUI from
within the main thread. The current tutorial backs off of that. But
based on that, I used what their tutorial said was safe for my only
JFrame, which was to fully build it in my main() method and then call
pack() and show() on it. Hey, Sun said it was OK! :)

What I failed to realize was that it would get me in trouble if I did it
more than once... So when I finally realized what my trouble was, I
changed my main class to create both GUI elements (the splash window and
the app's lone JFrame), but not to display them from that code.
Instead, I create a Runnable and pass it to SwingUtilities.invokeLater
so that it is indeed run on the EDT as Swing wants me to do.

Now, however, I find out that my consistent use of show() and hide() on
Window subclasses is being deprecated in 1.5. Drat!

= Steve =
 
R

Roedy Green

What I failed to realize was that it would get me in trouble if I did it
more than once... So when I finally realized what my trouble was, I
changed my main class to create both GUI elements (the splash window and
the app's lone JFrame), but not to display them from that code.
Instead, I create a Runnable and pass it to SwingUtilities.invokeLater
so that it is indeed run on the EDT as Swing wants me to do.

Bong!! I have always assumed the thread that ran main was ALSO the
Swing thread and the AWT thread. I gather this is NOT so.

This may explain my frustration with programs that would not stop even
after I closed all the Frames.
 
M

Michael Borgwardt

aruna said:
How memory leaks in java. What are the different ways in which
memory can leak. I know of tools which eliminate the leaks,
but I want to know what causes leaks, so that I can practice
not to write a program which leaks memory?

This is ultimately futile. There can always be memory leaks hidden in
some API, with objects holding on to references you wouldn't expect them
to (sometimes even without mentioning it in the documentation). One
such example is ObjectOutputStream which keeps references to all objects
written to it until you call close() or reset(). This can even happen
with code you write yourself if you forget about the details after a
while.

Sure, you can avoid most memory leaks by knowing about a few common
pitfalls, but at some point you'll run into one anyway and have to
make use of a profiler.
 
T

Thomas Weidenfeller

Steve said:
Now, however, I find out that my consistent use of show() and hide() on
Window subclasses is being deprecated in 1.5. Drat!

show() and hide() hide are finally consistently deprecated. They were
already deprecated on a number of classes for some time. Use
setVisible(true), setVisible(false) instead.

/Thomas
 
T

Thomas Weidenfeller

Roedy said:
Bong!! I have always assumed the thread that ran main was ALSO the
Swing thread and the AWT thread. I gather this is NOT so.

That was never the case. Sun just gave a "license" that it was ok to
create and change a component outside the EDT as long as it hadn't been
realized (shown).

For reasons Sun apparently doesn't understand, or doesn't want to
explain, they have withdrawn that "license" - partly. Quote from

http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

<quote>
Note: We used to say that you could create the GUI on the main thread as
long as you didn't modify components that had already been realized.
....
While this worked for most applications, in certain situations it could
cause problems. Out of all the demos in the Swing Tutorial, we
encountered a problem only in ComponentEventDemo. In that case,
sometimes when you launched the demo, it would not come up because it
would deadlock when updating the text area if the text area had not yet
been realized, while other times it would come up without incident.

To avoid the possibility of thread problems, we recommend that you use
invokeLater to create the GUI on the event-dispatching thread for all
new applications. If you have old programs that are working fine they
are probably OK; however you might want to convert them when it's
convenient to do so.
</quote>

Note the "clear" and "unambiguous" wording? :-(

/Thomas
 
S

Steve W. Jackson

Thomas Weidenfeller said:
:Steve W. Jackson wrote:
:> Now, however, I find out that my consistent use of show() and hide() on
:> Window subclasses is being deprecated in 1.5. Drat!
:
:show() and hide() hide are finally consistently deprecated. They were
:already deprecated on a number of classes for some time. Use
:setVisible(true), setVisible(false) instead.
:
:/Thomas

You'll note that I said on Window subclasses (since I only use Swing,
that mostly means JFrame and JDialog for me).

In most situations, I don't have need of directly changing the
visibility of any component other than an actual window, and when those
rare instances occur I have no problem using setVisible(). But it's
always seemed unnatural to me NOT to say show() or hide() where an
actual window is concerned. I don't see anything inconsistent about
using such methods for top-level containers only. But when we do get
ready to move up to 1.5, I'll now have to like it or lump it. :)

= Steve =
 
J

Jesper Nordenberg

How memory leaks in java. What are the different ways in which
memory can leak. I know of tools which eliminate the leaks,
but I want to know what causes leaks, so that I can practice
not to write a program which leaks memory?

A memory leak in Java occurs when you have multiple references to an
object and forget to update one of these. For example, you might have
references to an object in a HashMap or an ArrayList which you forget
to remove. Search Google for "java memory leak" and you will get some
informative hits.

/Jesper Nordenberg
 
J

Jesper Nordenberg

Steve W. Jackson said:
The garbage collection system truly is an improvement over what C++
users have had to do, IMO. And many common references will in fact get
cleaned up. We had some concerns about whether a HashMap, ArrayList or
Vector, for instance, needed to be cleared before it would get
collected. Our testing showed that it got collected sooner if we
cleared the contents, but that it would still get collected even if we
didn't. I rather suspect that simple "circular" references, where two
objects refer to each other, but neither can be found by my code, also
get collected properly, though we weren't concerned about that (that is,
after all, one of the strengths of Java).

Of course they are collected (otherwise Java would suck quite bad :).
Every object that is not reachable from local (including 'this') or
static references will be collected sooner or later. Sun's
recommendation is not to nullify references (or clearing ArrayList's)
yourself because this will decrease the performance of the GC.
But we fought a long, hard
battle over much more complex references eating up our memory, so we
eventually added dispose() methods in a number of our own complex
(non-GUI) classes to resolve the problem by ensuring that our references
got zapped, or caused subordinate objects to do their own dispose()
kinds of work.

This sounds like a bad design. If you're concerned with the memory
usage of your application, you should try tuning the GC, not
"disposing" objects yourself.

/Jesper Nordenberg
 
R

Roedy Green

Search Google for "java memory leak" and you will get some
informative hits.

leak is the wrong term. It refers to ram locked with NOTHING pointing
to it. What you are talking about is called packratting or loitering.
 
R

Roedy Green

Sun's
recommendation is not to nullify references (or clearing ArrayList's)
yourself because this will decrease the performance of the GC.


The GC itself is equally efficient. It is just that nullifying the
individual references does nothing to help the gc, so that work is
wasted.

Further, if by some fluke the gc occurred half way through you
nullifying the individual references it would only recover half the
space the first time. Had you killed the master reference in one
blow, it would have recovered all of it.
 
S

Steve W. Jackson

::> The garbage collection system truly is an improvement over what C++
:> users have had to do, IMO. And many common references will in fact get
:> cleaned up. We had some concerns about whether a HashMap, ArrayList or
:> Vector, for instance, needed to be cleared before it would get
:> collected. Our testing showed that it got collected sooner if we
:> cleared the contents, but that it would still get collected even if we
:> didn't. I rather suspect that simple "circular" references, where two
:> objects refer to each other, but neither can be found by my code, also
:> get collected properly, though we weren't concerned about that (that is,
:> after all, one of the strengths of Java).
:
:Of course they are collected (otherwise Java would suck quite bad :).
:Every object that is not reachable from local (including 'this') or
:static references will be collected sooner or later. Sun's
:recommendation is not to nullify references (or clearing ArrayList's)
:yourself because this will decrease the performance of the GC.
:
:> But we fought a long, hard
:> battle over much more complex references eating up our memory, so we
:> eventually added dispose() methods in a number of our own complex
:> (non-GUI) classes to resolve the problem by ensuring that our references
:> got zapped, or caused subordinate objects to do their own dispose()
:> kinds of work.
:
:This sounds like a bad design. If you're concerned with the memory
:usage of your application, you should try tuning the GC, not
:"disposing" objects yourself.
:
:/Jesper Nordenberg

We spent many hours identifying the source of our memory problems,
including a great deal of tuning. Since we have no direct control over
how much memory is present and cannot change min and max heap sizes
dynamically, tuning in a single user application environment doesn't
yield nearly as much benefit as you seem to suggest. You can get much
greater control in a server environment with a single JVM, and where you
have full knowledge beforehand of the environment.

If you're not concerned with the memory usage of your application, then
perhaps you're in the wrong line of work.
 
P

Phil Earnhardt

Sun would have us believe that it's "theoretically" impossible to get a
memory leak.

Where? What are you referring to?
But that's flatly not true.

I don't think you're drawing a distinction between a "memory leak" as
Roedy described above and what I would call an "object leak".
It can happen in complex
objects beyond just Swing components. Been there, done that. And there
are commercial tools aimed at helping find leaks so that you can resolve
them. We happen to use OptimizeIt, now sold by Borland.

If you had a "memory leak" as Roedy described it, such tools would be
incapable of doing any of that. OptimizeIt can only address issues
about issues with GCing objects and not random blocks of memory.

Tools for finding object leaks are light years ahead of the tools to
locate such problems in C/C++ code. It would have been problematic to
have a runtime tool that could find memory leaks in an arbitrary C/C++
binary in the way that OptimizeIt can locate object leaks in a Java
program. FWIR, the way people dealt with such problems was to write
their own wrappers around malloc()/free() or buy commercial packages
that did the same. But you had to deal with things like this at
compile time, and you often had to change the actual source code to
comply with the semantics for the malloc()/free() wrappers. Ugly.
The garbage collection system truly is an improvement over what C++
users have had to do, IMO. And many common references will in fact get
cleaned up. We had some concerns about whether a HashMap, ArrayList or
Vector, for instance, needed to be cleared before it would get
collected. Our testing showed that it got collected sooner if we
cleared the contents, but that it would still get collected even if we
didn't. I rather suspect that simple "circular" references, where two
objects refer to each other, but neither can be found by my code, also
get collected properly, though we weren't concerned about that (that is,
after all, one of the strengths of Java). But we fought a long, hard
battle over much more complex references eating up our memory,

It's difficult to comment definitively about that unless you posted
some code. The main question is whether or not those complex
references you created were an efficient way to deal with your
problem. I've seen some horrendous examples of code that attempted to
micro-manage their objects and, in the process, created objects that
couldn't be GC'd.

I've only worked with OptimizeIt a limited amount several years ago. I
was struck with the ease that it could be used to rapidly locate where
the object leaks were happening. Of course, simply locating the
culprit is only the start of fixing the problem.
= Steve =

--phil
 

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

Similar Threads

Debugging memory leaks 20
DOMParser memory leaks 2
memory leaks 4
memory leak jconsole 2
Memory leaks 2
pthread memory leaks 15
find memory leaks in running program 1
memory manager to prevent memory leaks 4

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top