Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2005

Tip: Looking for answers? Try searching our database.

Running out of memory gracefully

Thread view: 
thomas_okken@hotmail.com - 10 Dec 2005 14:49 GMT
I'm working on a rather memory-hungry application. There's not much I
can do to make the app use less memory, but I'm hoping that at least I
can find a way to handle low-memory situations better.
Currently, when memory runs out (typically as a result of a background
thread loading a huge table from a database), an OutOfMemoryError gets
thrown. There's no telling *where* this error gets thrown; if you're
lucky, it happens in the table-loading thread so table loading stops
but the rest of the app keeps working; if you're unlucky, the AWT Event
or Repaint threads die, and then you're stuck with a fatally hosed
application.

Years ago, when programming on the Macintosh, I used an OS function
called SetGrowZone() to register a callback, which the memory manager
would invoke when it was having trouble fulfilling a memory allocation
request. My approach was to allocate a big chunk of memory at
application startup time, and when my GrowZone callback got called, I
would release that chunk of memory to give the application some extra
breathing room, and simultaneously display a dialog box warning the
user that memory was getting dangerously low.

I'm trying to find a way to implement such a warning mechanism in Java,
but all I have come up with so far are "soft references". The problem
is that the Java API document only says "Virtual machine
implementations are [...] encouraged to bias against clearing
recently-created or recently-used soft references."
It would be more helpful if a reference type existed that would
guarantee that its referent is only deleted as a last resort; with such
a reference I could simply create, say, a 5-megabyte object, point such
a reference at it, and in its finalizer, pop up a warning message...
But I don't see a reliable way to achieve this. Do I really have no
choice but to wait until an OutOfMemoryError hits me in the face? (I
guess I could periodically call Runtime.gc() followed by checking
Runtime.freeMemory() + Runtime.maxMemory() - Runtime.totalMemory()...
Not very elegant!)

- Thomas
abigale_carson@yahoo.com - 10 Dec 2005 14:57 GMT
Hi Thomas,

As far as I know, soft reference is your best bet.  What you might do
is simply wait for a given reference to die, and then do the
freeMemory() + maxMemory() - totalMemory() trick.

Using soft references for this purpose has been discussed before, for
instance here:

http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/a0325
c0ce7e1b61d/8f57775430270c76?lnk=st&q=soft-reference+memory-management&rnum=1#8f
57775430270c76


or, if that breaks,

http://linkfrog.net/dabp

or here:

http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/9f208
5b13a5609ff/f239782998c1c769?lnk=st&q=soft-reference+memory-management&rnum=2#f2
39782998c1c769


--or--

http://linkfrog.net/dabq

hope that helps, Abigale
Andrew Thompson - 10 Dec 2005 15:06 GMT
> I'm working on a rather memory-hungry application. There's not much I
> can do to make the app use less memory, but I'm hoping that at least I
> can find a way to handle low-memory situations better.
...
I note you've struck upon the likely courses of action, for some
more detailed discussion along those lines, check this thread..
<http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/0da2b
ab2d76fc1de/fe7f2bb3eb99d626#fe7f2bb3eb99d626
>

Signature

Andrew Thompson
physci, javasaver, 1point1c, lensescapes - athompson.info/andrew

thomas_okken@hotmail.com - 10 Dec 2005 15:30 GMT
OK, I guess SoftReference does deserve a closer look then. I'll just
try creating one and using a ReferenceQueue to find out when it is
cleared; if I find that the GC is overly aggressive in deleting it, I
can always fall back on the tired periodic-check approach, but if the
GC behaves like I hope it does, this should work well. (I'll also keep
the tip about pre-creating a warning dialog in mind!)
Thanks for the pointers!

- Thomas
Thomas Hawtin - 10 Dec 2005 20:22 GMT
> I'm working on a rather memory-hungry application. There's not much I
> can do to make the app use less memory, but I'm hoping that at least I
[quoted text clipped - 6 lines]
> or Repaint threads die, and then you're stuck with a fatally hosed
> application.

I suggest referencing non-essential, recreatable data through soft
references. On some condition you can determine that you have come
sufficiently close to running out of memory.

> Years ago, when programming on the Macintosh, I used an OS function
> called SetGrowZone() to register a callback, which the memory manager
[quoted text clipped - 4 lines]
> breathing room, and simultaneously display a dialog box warning the
> user that memory was getting dangerously low.

You get something like this for free. Before OutOfMemoryError is thrown,
soft and weak references will have been cleared. In any case,
OutOfMemoryError will still be thrown even while there is still quite a
lot of memory recovered. If there really was very little memory left,
the garbage collector would be running full time.

> I'm trying to find a way to implement such a warning mechanism in Java,
> but all I have come up with so far are "soft references". The problem
[quoted text clipped - 10 lines]
> Runtime.freeMemory() + Runtime.maxMemory() - Runtime.totalMemory()...
> Not very elegant!)

You could create a soft reference to a large area of memory and poll it
regularly. However, the information will be much the same as you get
from Runtme. You might as well use soft references for some useful data.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Alun Harford - 11 Dec 2005 00:14 GMT
>> I'm working on a rather memory-hungry application. There's not much I
>> can do to make the app use less memory, but I'm hoping that at least I
[quoted text clipped - 25 lines]
> lot of memory recovered. If there really was very little memory left, the
> garbage collector would be running full time.

While this will almost always work, and is possibly the best way to do it
(unless there's a way to use less memory), you should bear in mind that
according to the standard, if an object is only softly reachable, it can be
garbage collected. Theoretically, SoftReferences can be treated as
WeakReferences by the JVM, and using them like this could be dangerous.
Currently, however, Sun's JVM isn't this nasty - but beware if you want to
use a more obscure one.

Alun Harford
Roedy Green - 10 Dec 2005 22:11 GMT
>Currently, when memory runs out (typically as a result of a background
>thread loading a huge table from a database), an OutOfMemoryError gets
>thrown.

Can you estimate how much RAM you are going to need, then test to see
if it is possible with a giant buffer allocation you can catch and
deal with aborting the query,  then free the buffer and carry on.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

steve - 12 Dec 2005 23:45 GMT
> I'm working on a rather memory-hungry application. There's not much I
> can do to make the app use less memory, but I'm hoping that at least I
[quoted text clipped - 32 lines]
>
>  - Thomas

1. don't load the "huge" database, find another solution to access the data.
which database is it?
perhaps we can come up with a solution to "randomly access " the data you
need from the database ,as you need it.

have a quick look at:
http://www.forward.com.au/javaProgramming/javaGuiTips/errorRecovery.html

and the jedit source code.

but ultimately , the out of memory error , will hose your app.

Steve
Steve W. Jackson - 14 Dec 2005 17:39 GMT
> > I'm working on a rather memory-hungry application. There's not much I
> > can do to make the app use less memory, but I'm hoping that at least I
[quoted text clipped - 46 lines]
>
> Steve

The site at that link says that the OutOfMemoryError is "not
necessarily" fatal.  But it's exceedingly difficult in most applications
to recover once it occurs.  It's worth pursuing some of the many places
on the web where good information about JVM heap tuning can be obtained.

The OP should note that the table-loading example cited will *not* save
him from this error merely because it's in a background thread.  This
error means that the entire JVM heap is full (or nearly so) and that,
after multiple attempts, sufficient memory cannot be allocated to it for
the task at hand to complete -- meaning creation of new objects called
for in his code.  In order to allow that table load to completely
"contain" the error without any impact elsewhere in his app, it would
need to be offloaded to another JVM entirely.  But, as suggested above,
pre-loading the entire table probably indicates that a redesign is in
order to get at the data.

The "years ago" example cited for Macintosh programming was, at best,
dubious in its day (and the new OS is entirely Unix-based and thus
doesn't suffer those problems any longer), but it doesn't translate into
Java due to the rather unique way that JVM memory is managed.  I
personally would love to see Sun devise a new method of JVM memory
management that would enable it to take better advantage of the virtual
memory management schemes in use in virtually all modern operating
systems, rather than a closed heap with an artificial glass ceiling.

= Steve =
Signature

Steve W. Jackson
Montgomery, Alabama

Thomas Okken - 14 Dec 2005 19:18 GMT
The SoftReferences approach works, but I had to refine it a bit: I
allocate a 5 megabyte chunk of memory, stick it in a SoftReference, and
then I monitor the ReferenceQueue to see when the chunk is deleted; at
that point, I enter a loop where I repeatedly check
Runtime.freeMemory() + RunTime.maxMemory() - RunTime.totalMemory() to
see whether it is safe to re-allocate the chunk (I consider it safe
when 10 megabytes is available).
Further, when the 5 MB chunk is deleted *and* there is insufficient
memory to re-allocate it immediately, the memory monitoring thread
pauses all active table-loading threads, and of course presents a
warning to the user.
Once enough free memory is available, start the whole process from the
beginning.

N.B. For reasons beyond the scope of this discussion, I have to load
entire tables at once; using more memory-efficient alternatives such as
scrollable result sets is not an option at this point. Fortunately, the
app already supports pausing and re-starting long table loads, so
suspending such loads programmatically in low-memory situations is easy
to implement and fits nicely within the existing design.

It should be noted that the JVM will clear SoftReferences even when it
doesn't have to. I noticed my 5 MB chunk getting cleared while my
program was trying to allocate 1 MB, with more than 15 MB of free
memory still being available. So, the SoftReference approach is better
than constantly polling free memory, but the fact that the reference is
cleared is *not* a reliable indication that memory is low. (Of course
as long as the reference is *not* cleared, that *is* a reliable
indication that memory is not low, and that's something.)
(All this probably depends on exactly which JVM you're using; I use
Sun's JDK 1.5.0_05 on Linux and Windows 2000 & XP).

So far my implementation of the SoftReference approach seems robust,
and I'm pretty happy with it. The Macintosh approach I mentioned in my
original post would still be preferable IMHO (but sadly Java does not
support this directly). I'm puzzled why Steve calls it "dubious"; I
would rather call it "perfect" because it provides a *reliable* way of
receiving advance warning that memory is running low -- and with zero
computational overhead. Of course it will only protect you as long as
you're trying to allocate memory in chunks that are smaller than the
"reserve" chunk, but in the case of my old Mac application, that was no
problem; I made the reserve 64kB, and in the one or two places where
memory was allocated in larger chunks, I just made sure to explicitly
check for allocation failures.

- Thomas


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.