Static methods and GC
Hello,
I've run into memory leak problem in my Java app. Before I start memory
profiling to know for sure where is the problem, I just wanted to ask You whether it is
reasonable to think that static methods can be causing this problem.
App design is as follows:
public static void main() {
...
for(...)
theStaticFunction();
...
}
private static void theStaticFunction() {
...
T[] memoryConsumingArray = ....
MyThread t = new MyThread(memoryConsumingArray);
t.start();
...
}
I'll provide you little additional explanation: In Main method other method,
which is private and static, is executed in loop.
Function creates local array which consumes a lot of heap memory (not
only because it has many elements, but also every element contains large
object graph). Next, this array is paased to thread constructor and
thread does further processing. Neither array nor its elements are assigned
to any static fields, they exist only in theStaticFunction, so should
be not reachable from roots of gc as soon as all threads finish they
work. Yet, program crashes with OutOfMemory from time to time unless it
is given 1GB of RAM or so, which is little too much :-) So I am trying
to examine potential memory leaks. The first suspect is this array, as
it is the dominating factor of memory consumption. Do you think that
problem might lie in large array being used from static function?
Normally arrays referenced by just local variables simply are swept
from existence when a method returns. You pass those arrays to threads
which also reference those arrays (I assume). Running threads aren't
garbage collected nor are the objects referenced by such a thread object.
kind regards,
Jos
Thx Josh, I know that, but then, after all spawned threads have died the array should be gc-ed, regardless of the fact that it was created within static function, am I right here?
> Thx Josh, I know that, but then, after all spawned
> threads have died the array should be gc-ed,
> regardless of the fact that it was created within
> static function, am I right here?
Yep, but does your method (it doesn't matter whether or not it's static)
create a new array for every single thread? That might be the cause of
an OutOfMemoryError. Reading your code it creates new threads in
rapid succession (one thread per loop iteration). If as many arrays are
created your program might consume too much memory.
kind regards,
Jos
>
> Yep, but does your method (it doesn't matter whether
> or not it's static)
> create a new array for every single thread? That
> might be the cause of
> an OutOfMemoryError. Reading your code it creates new
> threads in
> rapid succession (one thread per loop iteration). If
> as many arrays are
> created your program might consume too much memory.
>
Well, during one function execution one thread is created, execution is forked: method performs its activities, while thread is processing the array. After function has ended its job it blocks, waiting for the thread to finish and then quits. So the next iteration creates new array and new thread but older array, due to what you wrote, should be gc-ed soon. Am I correct here?
> Well, during one function execution one thread is created, execution
> is forked: method performs its activities, while thread is processing
> the array. After function has ended its job it blocks, waiting for the
> thread to finish and then quits. So the next iteration creates new array
> and new thread but older array, due to what you wrote, should be gc-ed
> soon. Am I correct here?
Yes, but this scenario begs for the question: why do you start a new
thread in the first place? The 'main' thread simply blocks and waits
until your 'worker' thread has finished. Why not do all the work in one
single 'main' thread?
kind regards,
Jos
> Yes, but this scenario begs for the question: why do
> you start a new
> thread in the first place? The 'main' thread simply
> blocks and waits
> until your 'worker' thread has finished. Why not do
> all the work in one
> single 'main' thread?
>
The thread communicates with LotusNotes client, and therefore it has to be one, this constraint is imposed by Lotus Notes API.
> The thread communicates with LotusNotes client, and therefore it
> has to be one, this constraint is imposed by Lotus Notes API.
You have to supply a bit more detail: is that Lotus Notes API a Java API?
Does it use JNI? Possibly the Lotus Notes implementation keeps a
reference to those arrays, who knows?
For starters: if you zero out (set to null) your references to those arrays
in your threads when the threads finish, there might surface a useful
indication that you can blame Lotus Notes for this ;-)
kind regards,
Jos
>
> You have to supply a bit more detail: is that Lotus
> Notes API a Java API?
Hmm, It's Java interface to Lotus Notes API
> Does it use JNI?
Perhaps it is used somewhere underneath, I do not know for sure, but I think so
> Possibly the Lotus Notes
> implementation keeps a
> reference to those arrays, who knows?
>
Maybe, but I'd be really suprised if it did. I derive this thread from Lotus Notes class and provide my own "worker method", overriding Lotus API abstract one, where I reference arrays. Arrays are specific to my program and since they are private fields in thread's class Lotus Notes layer does not have any way of referencing them, nor any reason for this matter
> For starters: if you zero out (set to null) your
> references to those arrays
> in your threads when the threads finish, there might
> surface a useful
> indication that you can blame Lotus Notes for this
> ;-)
>
Well, I've become deeply suspect of whether these Notes' threads do really finish :-) My method finishes for sure, but it is just a part of run() method of Lotus Notes thread. Anyway, you can always safely blame Lotus Notes for almost anything :-)
Vague questions for you: if your method joins the other thread that other
thread must finish somehow because your method returns. Do you use
a join for this? Are you absolutely, positively, definitely sure that you don't
pass those arrays on to something else?
Sorry for being so vague but this is all I can do given the information
you supplied.
kind regards,
Jos
> Vague questions for you: if your method joins the
> other thread that other
> thread must finish somehow because your method
> returns. Do you use
> a join for this?
If you mean join() method then yes
> Are you absolutely, positively,
> definitely sure that you don't
> pass those arrays on to something else?
>
No, I pass them somewhere else, but they are always referenced only by objects local to the function in question.
> Sorry for being so vague but this is all I can do
> given the information
> you supplied.
Yes, I understand. Would you recommend memory profiling?
Thank you
> > Sorry for being so vague but this is all I can do given the information
> > you supplied.
>
> Yes, I understand. Would you recommend memory profiling?
I guess so (as a last resort). I normally favour a few System.out.println()
invocations but maybe memory profiling and keeping an eye right on the
process as it goes may help too.
> Thank you
You're welcome and
kind regards,
Jos
Thank you for detailed info.