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 / September 2005

Tip: Looking for answers? Try searching our database.

ImageJ memory leak?

Thread view: 
phsamuel@gmail.com - 15 Sep 2005 19:49 GMT
Hi,

I have memory leakage problem using ImagePlus.show() when I use ij
library outside ImageJ. Even after I close the imageplus window, the
memory is not free. I tested the similar situation inside ImageJ and I
don't encounter any memory problem. My test code is attached at the
end. Press the "Show Image" button to show a big image stack. Press the
"show memory usage" to check memory usage. Apparently, no memory is
free after the big image stack is closed...

I am not a very experience Java/ImageJ programmer. Any advice will be
helpful.

samuel

//--------------------------------------------------
package bugReveal;

import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.process.ByteProcessor;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;

public class ImagePlusShow extends JFrame {

 private JPanel jContentPane = null;  //  @jve:decl-index=0:
 private JButton jButton = null;  //  @jve:decl-index=0:
 private JButton jButton1 = null;

 ImagePlus createBigStackImagePlus()
   {
     ImageStack ims=new ImageStack(640,480);
     ByteProcessor bp;
     for (int i=0;i<50;i++)
       {
         bp = new ByteProcessor(640,480);
         ims.addSlice("",bp);
       }
     ImagePlus imp=new ImagePlus("",ims);
     return imp;
   }

 /**
  * This method initializes jButton
  *
  * @return javax.swing.JButton
  */
 private JButton getJButton() {
   if (jButton == null) {
     jButton = new JButton();
     jButton.setText("Show Image");
     jButton.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(java.awt.event.ActionEvent e) {
         createBigStackImagePlus().show();
       }
     });
   }
   return jButton;
 }

 /**
  * This method initializes jButton1
  *
  * @return javax.swing.JButton
  */
 private JButton getJButton1() {
   if (jButton1 == null) {
     jButton1 = new JButton();
     jButton1.setText("show memory usage");
     jButton1.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(java.awt.event.ActionEvent e) {
         System.out.println(IJ.currentMemory());
       }
     });
   }
   return jButton1;
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
   new ImagePlusShow();
 }

 /**
  * This is the default constructor
  */
 public ImagePlusShow() {
   super();
   initialize();
 }

 /**
  * This method initializes this
  *
  * @return void
  */
 private void initialize() {
   this.setSize(300, 200);
   this.setContentPane(getJContentPane());
   this.setTitle("JFrame");
   this.pack();
   this.setVisible(true);
 }

 /**
  * This method initializes jContentPane
  *
  * @return javax.swing.JPanel
  */
 private JPanel getJContentPane() {
   if (jContentPane == null) {
     jContentPane = new JPanel();
     jContentPane.setLayout(new BorderLayout());
     jContentPane.add(getJButton(), java.awt.BorderLayout.CENTER);
     jContentPane.add(getJButton1(), java.awt.BorderLayout.SOUTH);
   }
   return jContentPane;
 }
 
}
Oliver Wong - 15 Sep 2005 20:16 GMT
> Hi,
>
[quoted text clipped - 5 lines]
> "show memory usage" to check memory usage. Apparently, no memory is
> free after the big image stack is closed...

[code snipped]

   I noticed that you create an ImageStack called "ims", fill it with 50
ByteProcessors, and then throw away the ims. Thus, the ims is available for
garbage collection. I don't know how bit a ByteProcessor is, but 50 doesn't
seem very big to me, which might explain why GC doesn't actually happen. Did
you try running the code with, say, 100'000 ByteProcessors, checking memory
usage, throwing them away, and then generating another 100'000
ByteProcessors and checking memory usage again to see if it has increased
significantly.

   AFAIK, you can't directly "force" garbage collection. The only trick I
can think of is to fill up more than half of your memory with
ByteProcessors, then dropping them, then trying to fill up more than half
your memory with ByteProcessors again. The second time you do this, you
wouldn't have enough room unless garbage collection occured (or unless JIT
does some obscure optimizations).

   - Oliver
Roedy Green - 15 Sep 2005 22:06 GMT
>    AFAIK, you can't directly "force" garbage collection.

you can try System.gc()  but that is only a hint.   It might be nice
to get a force on that to use for experiments.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Roedy Green - 16 Sep 2005 03:10 GMT
>I have memory leakage problem using ImagePlus.show() when I use ij
>library outside ImageJ. Even after I close the imageplus window, the
[quoted text clipped - 3 lines]
>"show memory usage" to check memory usage. Apparently, no memory is
>free after the big image stack is closed...

You likely don't have a leak, but rather packratting -- where you hold
onto old objects you no longer need.  See
http://mindprod.com/jgloss/packratting.html

To track down just what the problem is, you want to know what kinds of
objects are plugging RAM . see
http://mindprod.com/jgloss/profiler.html
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

phsamuel@gmail.com - 16 Sep 2005 04:44 GMT
Thanks a lot for the advice. I tried System.gc() but the problem
persists. I'll try more and probably send an email to the author of
ImageJ. The weird thing is that I have no problem at all if I run
inside ImageJ as a plugin. It only needs minimal modification and is
shown below.

samuel

//------------------------------------
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.process.ByteProcessor;
import ij.plugin.*;

import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;

public class ImagePlusShow_memory_check extends JFrame implements
PlugIn {

 private JPanel jContentPane = null;  //  @jve:decl-index=0:
 private JButton jButton = null;  //  @jve:decl-index=0:
 private JButton jButton1 = null;

 ImagePlus createBigStackImagePlus()
   {
     ImageStack ims=new ImageStack(640,480);
     ByteProcessor bp;
     for (int i=0;i<50;i++)
       {
         bp = new ByteProcessor(640,480);
         ims.addSlice("",bp);
       }
     ImagePlus imp=new ImagePlus("",ims);
     return imp;
   }

 /**
  * This method initializes jButton
  *
  * @return javax.swing.JButton
  */
 private JButton getJButton() {
   if (jButton == null) {
     jButton = new JButton();
     jButton.setText("Show Image");
     jButton.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(java.awt.event.ActionEvent e) {
         createBigStackImagePlus().show();
       }
     });
   }
   return jButton;
 }

 /**
  * This method initializes jButton1
  *
  * @return javax.swing.JButton
  */
 private JButton getJButton1() {
   if (jButton1 == null) {
     jButton1 = new JButton();
     jButton1.setText("show memory usage");
     jButton1.addActionListener(new java.awt.event.ActionListener() {
       public void actionPerformed(java.awt.event.ActionEvent e) {
         IJ.freeMemory();
         System.out.println(IJ.currentMemory());
       }
     });
   }
   return jButton1;
 }

    public void run(String arg) {
    }

 /**
  * This is the default constructor
  */
 public ImagePlusShow_memory_check() {
   super();
   initialize();
 }

 /**
  * This method initializes this
  *
  * @return void
  */
 private void initialize() {
   this.setSize(300, 200);
   this.setContentPane(getJContentPane());
   this.setTitle("JFrame");
   this.pack();
   this.setVisible(true);
 }

 /**
  * This method initializes jContentPane
  *
  * @return javax.swing.JPanel
  */
 private JPanel getJContentPane() {
   if (jContentPane == null) {
     jContentPane = new JPanel();
     jContentPane.setLayout(new BorderLayout());
     jContentPane.add(getJButton(), java.awt.BorderLayout.CENTER);
     jContentPane.add(getJButton1(), java.awt.BorderLayout.SOUTH);
   }
   return jContentPane;
 }
 
}
Oliver Wong - 16 Sep 2005 15:38 GMT
> Thanks a lot for the advice. I tried System.gc() but the problem
> persists.

   As I said earlier, there is direct way to force a garbage collection.
Roedy mentioned System.gc(), but with the caveat that it is only a
suggestion to the runtime to start garbage collection; not a mandatory
command to do so.

> I'll try more and probably send an email to the author of
> ImageJ. The weird thing is that I have no problem at all if I run
> inside ImageJ as a plugin. It only needs minimal modification and is
> shown below.

   As I said earlier, your test only creates 50 objects. Maybe the runtime
feels that the amount of memory used up by these objects is so negligeable
as to not require wasting time with garbage collection. This is why I
recommended you try to exaust your system memory by taking up, say 75% of
it, then discarding all those objects, then allocating another 75% of your
memory, to force a garbage collection to occur.

   - Oliver
phsamuel@gmail.com - 16 Sep 2005 17:36 GMT
I tried what you suggested already. 50 objects are actually pretty big.
It used 15M. If I clicked "show image" three times. It already used up
75% of the memory. The default memory allocation seems to be around
60M. The application crashes when I click the fourth time...

samuel
Oliver Wong - 16 Sep 2005 17:47 GMT
>I tried what you suggested already. 50 objects are actually pretty big.
> It used 15M. If I clicked "show image" three times. It already used up
> 75% of the memory. The default memory allocation seems to be around
> 60M. The application crashes when I click the fourth time...

   Okay, thank you. What does ImagePlus.show() do? Display the image in a
new frame? If so, when you close the window, do you need to dipose it
somehow? If ImagePlus extends JFrame, you might need to call
setDefaultCloseOperation(DISPOSE_ON_CLOSE) on it.

   - Oliver
Roedy Green - 18 Sep 2005 06:47 GMT
>Thanks a lot for the advice. I tried System.gc() but the problem
>persists.

Of course the error persisted. Java does not give you an out of memory
error until it has exhausted gc.

see http://mindprod.com/runerrormessages.html#OUTOFMEMORYERROR
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Roedy Green - 18 Sep 2005 07:02 GMT
>import ij.IJ;
>import ij.ImagePlus;
>import ij.ImageStack;
>import ij.process.ByteProcessor;
>import ij.plugin.*;

It hard to help you since we don't have this code and are not familiar
with how it works.

I noticed this little piece, not directly your problem, but a problem
nonetheless with all your code:

   *
   * @return javax.swing.JPanel
   */
  private JPanel getJContentPane()
     {
     if ( jContentPane == null )
        {
        jContentPane = new JPanel();
        jContentPane.setLayout(new BorderLayout());
        jContentPane.add(getJButton(), java.awt.BorderLayout.CENTER);
        jContentPane.add(getJButton1(), java.awt.BorderLayout.SOUTH);
        }
     return jContentPane;
     }

  }

Get implies simply fetching some value that already exists.  I would
called that "buildStrawberryPanel" which is more indicative of what it
really does.

Also you have used a word "ContentPane" that has very specific meaning
in a nonstandard way. This is extremely confusing.

Instead of jContentPane call that variable  the wombatPanel or
whatever it is.

Use names that mean something not, generic words like button1 and
button2 untess the buttons are literally labelled 1 and 2.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Chris Smith - 18 Sep 2005 15:36 GMT
>    private JPanel getJContentPane()
>       {
[quoted text clipped - 11 lines]
> called that "buildStrawberryPanel" which is more indicative of what it
> really does.

I don't see a problem, on the other hand.  This is a straight-forward
implementation of lazy initialization (assuming that multithreading is
not a requirement), and follows all the standard conventions of a lazy-
initialization accessor.

Note that after the very first time it's called, it no longer builds
anything.

Signature

www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation



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.