ImageJ memory leak?

Discussion in 'Java' started by phsamuel@gmail.com, Sep 15, 2005.

  1. Guest

    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;
    }

    }
    , Sep 15, 2005
    #1
    1. Advertising

  2. Oliver Wong Guest

    <> wrote in message
    news:...
    > 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...


    [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
    Oliver Wong, Sep 15, 2005
    #2
    1. Advertising

  3. Roedy Green Guest

    On Thu, 15 Sep 2005 19:16:48 GMT, "Oliver Wong" <>
    wrote or quoted :

    > 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.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Again taking new Java programming contracts.
    Roedy Green, Sep 15, 2005
    #3
  4. Roedy Green Guest

    On 15 Sep 2005 11:49:46 -0700, wrote or quoted :

    >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...


    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
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Again taking new Java programming contracts.
    Roedy Green, Sep 16, 2005
    #4
  5. Guest

    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;
    }

    }
    , Sep 16, 2005
    #5
  6. Oliver Wong Guest

    <> wrote in message
    news:...
    > 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
    Oliver Wong, Sep 16, 2005
    #6
  7. Guest

    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
    , Sep 16, 2005
    #7
  8. Oliver Wong Guest

    <> wrote in message
    news:...
    >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
    Oliver Wong, Sep 16, 2005
    #8
  9. Roedy Green Guest

    On 15 Sep 2005 20:44:00 -0700, wrote or quoted :

    >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
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Again taking new Java programming contracts.
    Roedy Green, Sep 18, 2005
    #9
  10. Roedy Green Guest

    On 15 Sep 2005 20:44:00 -0700, wrote or quoted :

    >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.


    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Again taking new Java programming contracts.
    Roedy Green, Sep 18, 2005
    #10
  11. Chris Smith Guest

    Roedy Green <> wrote:
    > 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.


    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.

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

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Sep 18, 2005
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. George

    ImageJ debuger

    George, Nov 29, 2003, in forum: Java
    Replies:
    1
    Views:
    449
    Andrew Thompson
    Nov 29, 2003
  2. Replies:
    1
    Views:
    3,841
    jfalt
    Jan 18, 2005
  3. academic
    Replies:
    10
    Views:
    635
    academic
    Feb 15, 2006
  4. DocBadwrench
    Replies:
    0
    Views:
    1,985
    DocBadwrench
    Oct 12, 2006
  5. bharath

    about imageJ package

    bharath, Mar 12, 2007, in forum: Java
    Replies:
    2
    Views:
    512
    Thomas Fritsch
    Mar 12, 2007
Loading...

Share This Page