views:

107

answers:

2

I'm having trouble with memory in a j2me application. (see another question)

I discovered that one class has a loop that doesn't stop until the application is closed. This loop is consuming all the memory available.

I didn't make this class so I don't know why things was done this way. So any suggestions are welcome.

Here is a simplified version of the class:

    import java.util.TimerTask;

    public class SomeClass extends TimerTask implements Runnable {
        private boolean running = false;
        private Thread thread;

        public void invokeThread() {
           running = true;
           thread = new Thread(this);
           thread.start();
        }

        public void run() {
           while(running) {

                try {
                  Thread.sleep(800);

                } catch (InterruptedException ex) {
                  ex.printStackTrace();
                }
                doSomeStuff();
           }
        }

        private void doSomeStuff() {     
            // do some stuff that consumes my memory
        }

        public void dispose() {
            running = false;   
        }

}

Another class calls SomeClass.invokeThread() and wait for some user response (this already spend some memory).

When the users ends inputting data this another class calls dispose() and the while loop doesn't stop, wait some minutes or try to navigate a bit more the application and you get an OutOfMemoryError.

Can you help me?

thanks

A: 

Without seeing what's going on inside of doSomeStuff() it's impossible to tell why the loop doesn't terminate. Obviously the routine is expecting that dispose() is eventually going to be called or that running will eventually be set to false manually. If the loop isn't terminating, then neither of these things are happening. You should examine the logic within doSomeStuff() to figure out why.

Jeff L
dispose() is being called. inside doSomeStuff() is some string manipulations (those that consumes the memory) and calls another method that God knows what it does.
Daniel Moura
+3  A: 

Try adding keyword volatile to the variable running:

private volatile boolean running = false;

This is done to ensure that your thread always uses master-copy of the variable, not the locally stored.

Malcolm
what is the master-copy of the variable?
Daniel Moura
Well, there are some optimizations that assume that the variables are only modified within the current thread. This allows to work not with the real variable, but with its copy in the thread and update the real variable (master-copy) from time to time. But in your case the flag variable can be modified by other code, so you have to mark this variable as volatile, and the thread will become aware that it has to take into account such possibility.
Malcolm
Amazing... works! thanks a lot
Daniel Moura
Mark this post as a solution, then. :)
Malcolm
The problem in this case is that for a non-volatile boolean `b`, the VM may rewrite `while (b) { ... }` to `if (b) { while (true) { ... } }`. Forgetting the `volatile` modifier is a most classic bug :)
gustafc
Good example! Well, I do this automatically, but it may be not obvious and some people forget to add this rare modificator.
Malcolm