开发者

Why does this code to fill an Array create a memory leak?

I have encountered a somewhat baffling problem with the simple task of filling an Array dynamically in Java. The following is a snapshot from where the problem originates:

entries = new Object[ (n = _entries.length + 1) ] ;

for(i = 0 ; i < n ; i++) {

            entry = ( i == (n - 1) )  ?  addition  :  _entries[i]  ;

            entries[i] = entry ;

            //...

}

Where _entries is a source Array (field of the class); entries is initialized as an Array of Object开发者_如何学Cs

Object[] entries = null ;

and addition is the Object to be added (passed as an Argument to the method this code is in).


The code passes the compiler but results in a memory-leak when called. I was able to narrow down the cause to the line where the code attempts to fill the new Array

 entries[i] = entry ;

however, I cannot think of any reason why this would cause a memory-leak. I'm guessing the root of the issue must be either an extremely stupid fault on my part or an extremely arcane problem with Java. :-)

If you need more background let me know.

Edit:

Tomcat's log tells me:

A web application appears to have started a thread named ... but has failed to stop it. This is very likely to create a memory leak.

Other than that obviously the page loading the class does not finish loading or loads very slowly.

Edit:

The problem might be somewhere else (at a more expected location) after all. Apparently Tomcat wasn't loading the class files all the time when I tried to pin down the faulty code and this mislead me a bit. I now suspect a infinte for-each loop caused by a defective Iterator implementation up in the call stack to be at fault. In any case, thanks for your input! Always much appreciated!


I will use a Collection (probably a Vector) instead of an Array as a work-around; still, I'd like to know what the problem here is.

TIA,

FK82


So, about your Tomcat log message:

A web application appears to have started a thread named ... but has failed to stop it. This is very likely to create a memory leak.

This says that your servlet or something similar started a new thread, and this thread is still running when your servlet finished its operation. It doesn't relate at all to your example code (if this code isn't the one starting the thread).

Superfluous threads, even more when each HTTP-request starts a new one (which does not finish soon) can create a memory leak, since each thread needs quite some space for its stack, and also may inhibit garbage-collection by referencing objects who are not needed anymore. Make sure that your thread is really needed, and think about using a threadpool instead (preferably container-managed, if this is possible).


I cannot see a memory leak, but your code is more complicated than it needs to be. How about this:

newLength = $entries.length + 1;
entries = new Object[ newLength ] ;

for(i = 0 ; i < newLength - 1 ; i++) {
        entries[i] = $entries[i];
        //...
}

entries[ newLength - 1 ] = addition;

No need to check if you are at the last entry all the time and you could use a array copy method as suggested by Alison.

Think of this post as a comment. I just posted it as an answer because I don't know how code is formatted in comments...


It is working for me,

please find the sample code. and change it to accordingly

class test {

 public static void main(String[] args) {


   String[] str = new String[]{"1","2","3","4","5","6"};

   int n=0;
   Object[] entries = new Object[ (n = 5 + 1) ] ;

    for(int i = 0 ; i < n ; i++) {

            Object entry = ( i == (n - 1) )  ?  new Object()  :  str [i]  ;

            entries[i] = entry ;



    }
   System.out.println(entries[3]);

 }

}


Perhaps by Memory Leak you are meaning an OutOfMemoryException? Sometime you get that in Java if you do not have the minimum heap size set high enough (and also a well defined max heap size too) when you start up. If there is not enough heap created at startup then you can sometimes use it up faster than the JVM has time to allocate more memory to the heap or to garbage collect. Unfortunately, there is no "right answer" here. You just have to play with different settings to get the right result (ie, known as "tuning the JVM"). In other words, this is more of an art than a science.

And in case you didn't know, you pass the arguments to the JVM on the command line when firing up your program -Xmin 250m -Xmax 1024m is an example. You must specify the values in megabytes. The first sets the minimum heap (at startup) to 250 megabytes. The second argument sets the max heap size at one gigabyte.

Just another thought to go by as I too am puzzled by how you could trace a memory leak to one line of code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜