Custom LayoutManager causes OutOfMemory

Hi

We created one custom LayoutManger.It works fine ,but when thw window is resized by dragging the window , system hangs and gives OutOfMemory error afters some time.

Screen contains one Panel on left side and other space hungry Panel or right side. The top level conatiner follows BorderLayout.

Left side Panel uses Custom Layout. If I'm removing this layout everything is perfect. Can anybody advise me where I gone wrong

import java.awt.Component;

import java.awt.Container;

import java.awt.Dimension;

import java.awt.Insets;

import java.awt.LayoutManager;

publicclass CustomLayoutManagerimplements LayoutManager{

publicstaticfinalint VERTICAL_GAP = 2;

publicstaticfinalint CELLHEIGHT = 25;

publicstaticint CELLWIDTH = 80;

publicstaticfinalint CELL_STARTX = 0;

privateint vgap = VERTICAL_GAP;

// private int minWidth = 0, minHeight = 0;

// p// preferredWidth = 0, preferredHeight = 0;

publicvoid addLayoutComponent(String arg0, Component arg1){

// TODO Auto-generated method stub

}

publicvoid removeLayoutComponent(Component arg0){

// TODO Auto-generated method stub

}

/* Required by LayoutManager. */

public Dimension preferredLayoutSize(Container parent){

//Always add the container's insets!

synchronized (parent.getTreeLock()){

Insets insets = parent.getInsets();

int ncomponents = parent.getComponentCount();

int w = 20;

int h = 0;

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

Component comp = parent.getComponent(i);

Dimension d = comp.getPreferredSize();

if (w < d.width){

w = d.width;

}

if (h < d.height){

h = d.height;

}

}

returnnew Dimension(insets.left + insets.right + w, insets.top

+ insets.bottom + (ncomponents * h) + (ncomponents - 1)

* vgap);

}

}

/* Required by LayoutManager. */

public Dimension minimumLayoutSize(Container parent){

synchronized (parent.getTreeLock()){

//Always add the container's insets!

Insets insets = parent.getInsets();

int ncomponents = parent.getComponentCount();

int w = 0;

int h = 0;

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

Component comp = parent.getComponent(i);

Dimension d = comp.getMinimumSize();

if (w < d.width){

w = d.width;

}

if (h < d.height){

h = d.height;

}

}

returnnew Dimension(insets.left + insets.right + w, insets.top

+ insets.bottom + (ncomponents * h) + (ncomponents - 1)

* vgap);

}

}

/* Required by LayoutManager. */

/*

* This is called when the panel is first displayed,

* and every time its size changes.

* Note: You CAN'T assume preferredLayoutSize or

* minimumLayoutSize will be called -- in the case

* of applets, at least, they probably won't be.

*/

publicvoid layoutContainer(Container parent){

Insets insets = parent.getInsets();

int maxWidth = parent.getSize().width - (insets.left + insets.right);

/**

* parentWidth is being set by resize of scrollpane :(

* Done lots of R&D,if u have better idea let me know

*

*/

_doLayout(parent, maxWidth);

}

/**

* Do the layout

* @param parent

* @param width

*/

privatevoid _doLayout(Container parent,int width){

int nComps = parent.getComponentCount();

Insets insets = parent.getInsets();

int x = 0, y = insets.top;

/**

* parentWidth is being set by resize of scrollpane :(

* Done lots of R&D,if u have better idea let me know

*

*/

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

Component c = parent.getComponent(i);

if (c.isVisible()){

Dimension d = c.getSize();

c.setBounds(CELL_STARTX, y, width, CELLHEIGHT);

y = y + CELLHEIGHT + vgap;

}

}

}

}

[7443 byte] By [Jobinesha] at [2007-10-3 3:35:57]
# 1

I think using non-dynamic values for layout manager implementation is wrong.

Try this small example:

import javax.swing.*;

import java.awt.*;

public class Jobi{

public Jobi(){

JFrame frame = new JFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel jp = new JPanel();

jp.setLayout(new CustomLayoutManager());

JScrollPane js = new JScrollPane(jp);

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

jp.add(new JLabel("label " + i));

}

frame.getContentPane().add(js, BorderLayout.CENTER);

frame.setSize(300, 500);

frame.setVisible(true);

}

public static void main(String[] args){

new Jobi();

}

}

hiwaa at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 2

This is substantially better than your original implementation.

Try reimplement other methods.

/* Required by LayoutManager. */

public Dimension preferredLayoutSize(Container parent) {

//Always add the container's insets!

synchronized (parent.getTreeLock()) {

Insets insets = parent.getInsets();

int ncomponents = parent.getComponentCount();

int w = 20;

int h = 0;

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

Component comp = parent.getComponent(i);

Dimension d = comp.getPreferredSize();

if (w < d.width) {

w = d.width;

}

if (h < d.height) {

h = d.height;

}

}

int x = insets.left + insets.right + w;

int y = insets.top + insets.bottom + (ncomponents * h)

+ (ncomponents - 1) * vgap;

int y2 = insets.top + insets.bottom + (ncomponents * CELLHEIGHT)

+ (ncomponents - 1) * vgap;

if (y2 > y){

y = y2;

}

return new Dimension(x, y);

}

}

hiwaa at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 3
Thank you very much Mr.Hiwa. I'll try it out.But one question...>>I think using non-dynamic values for layout manager implementation is wrong.Why it is so? Can u give me more detailed answer for the sameThanks a lotJobinesh
Jobinesha at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 4

> Thank you very much Mr.Hiwa. I'll try it out.

> But one question...

> >>I think using non-dynamic values for layout manager

> implementation is wrong.

> Why it is so? Can u give me more detailed answer for

> the same

>

> Thanks a lot

> Jobinesh

If values are fixed statics, and the number of laid-out components is huge, you could naturally get an OOME.

hiwaa at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 5

Thanks again Hiwa...

> If values are fixed statics, and the number of

> laid-out components is huge, you could naturally get

> an OOME.

I agree that static values are gnerally wrong for a good LayoutManger.

Still I'm not getting one point., How does it cause OOME ?. Some where it's going to infinite loop?If yes, where does it happen?

Thanks alot for your patience!!!

Jobinesh

Jobinesha at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 6

Sorry but for your particular OOME, we should see a small demo code that is generally compilable, runnable and could reproduce your problem. See: http://homepage1.nifty.com/algafield/sscce.html and [url=http://riters.com/JINX/index.cgi/Suggestions_20for_20Asking_20Questions_20on_20Newsgroups]this wiki.[/url]

hiwaa at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 7
I assume that you do print out the stack trace! Which line does the OutOfMemory exception stack trace say is the offending line?
sabre150a at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 8

>I assume that you do print out the stack trace! Which line does the OutOfMemory exception stack trace say is the offending line?

Stacktarce doesn't give me any information.It just says OutOfMemory. Actually we added one defualt handler for exceptions from EDT. It reaches there.

I 'll try to present the sample code, as this happens with a huge application, may not help us to rectify the exact problem.

Anyway thank all for all help and valuable suggestions.

Jobinesha at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 9

Hi,

Issue is rectified. Two issues were there.

1. Some portion of the code was not thread safe( not in EDT).

2. Made changes in custom layoutmanager as some components are

accessed by multiples threads at he same time. (This was the major cluprit . Theoretically ,resize of the main frame was in EDT and it should not have happened, no idea why it happened)

Thanks

Jobinesh

Jobinesha at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 10

> Issue is rectified. Two issues were there.

> 1. Some portion of the code was not thread safe( not

> in EDT).

> 2. Made changes in custom layoutmanager as some

> components are

> accessed by multiples threads at he same time. (This

> was the major cluprit . Theoretically ,resize of the

> main frame was in EDT and it should not have

> happened, no idea why it happened)

>

If these are your problems then you have a more fundamental problem in that layout managers are only used in the Swing event thread so some of your code must be updating a Swing component outside of the Swing event thread.

sabre150a at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...
# 11

> Hi,

>

> Issue is rectified. Two issues were there.

> 1. Some portion of the code was not thread safe( not

> in EDT).

> 2. Made changes in custom layoutmanager as some

> components are

> accessed by multiples threads at he same time. (This

> was the major cluprit . Theoretically ,resize of the

> main frame was in EDT and it should not have

> happened, no idea why it happened)

>

> Thanks

> Jobinesh

You should have used invokeLater(), invokeAndWait() or SwingWorker class for calling Swing code from those non-EDT threads.

hiwaa at 2007-7-14 21:30:49 > top of Java-index,Desktop,Core GUI APIs...