JDK-4623196 : GridBagLayout.minimumLayoutSize throws unexpected AIOOBE
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_2.5
  • CPU: sparc
  • Submitted: 2002-01-14
  • Updated: 2005-12-01
  • Resolved: 2005-04-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 6
6 b33Fixed
Related Reports
Relates :  
Description
Name: idR10193			Date: 01/14/2002


Call to the method minimumLayoutSize of GridBagLayout leads to
unexpected java.lang.ArrayIndexOutOfBoundsException (actually it 
happends in GetLayoutInfo).

============================== Start of addLC.java =======================
import java.awt.*;

public class addLC {

    public static void main(String argv[]) {
        GridBagLayout gbl = new GridBagLayout();
    
        Container parent = new Container();
        parent.setSize(801, 601);
        parent.setLayout(gbl);
    
        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridx = 0;
        gbc.gridy = Integer.MAX_VALUE;
        gbc.gridwidth = Integer.MAX_VALUE;
        gbc.gridheight = 0;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.weightx = 0;
        gbc.weighty = Double.MAX_VALUE;
        gbc.fill = GridBagConstraints.NONE;
        gbc.ipadx = 0;
        gbc.ipady = Integer.MAX_VALUE;
        Insets insets = new Insets(0, 1, 2, 3);
    
        Component comp = new Component(){};
        comp.setSize(40, 30);
    
        parent.add(comp, gbc);
    
        Dimension new_sz = gbl.minimumLayoutSize(parent);

        System.out.println(new_sz);
    }
}
============================== End of AddLC.java =======================
Output under JDK version "1.4.0-rc-b91" ===============================

~/bugs;
javac addLC.java;java addLC
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
        at java.awt.GridBagLayout.GetLayoutInfo(GridBagLayout.java:872)
        at java.awt.GridBagLayout.getLayoutInfo(GridBagLayout.java:791)
        at java.awt.GridBagLayout.minimumLayoutSize(GridBagLayout.java:640)
        at addLC.main(addLC.java:31)
~/bugs;
=======================================================================

======================================================================

Comments
SUGGESTED FIX ------- GridBagLayout.java ------- *** /tmp/geta21425 Fri Nov 14 11:51:21 2003 --- /tmp/getb21425 Fri Nov 14 11:51:21 2003 *************** *** 8,13 **** --- 8,14 ---- import java.util.Hashtable; import java.util.Vector; + import java.util.ArrayList; class GridBagLayoutInfo implements java.io.Serializable { int width, height; /* number of cells horizontally, vertically */ *************** *** 18,28 **** double weightY[]; /* largest weight in each row */ GridBagLayoutInfo () { ! minWidth = new int[GridBagLayout.MAXGRIDSIZE]; ! minHeight = new int[GridBagLayout.MAXGRIDSIZE]; ! weightX = new double[GridBagLayout.MAXGRIDSIZE]; ! weightY = new double[GridBagLayout.MAXGRIDSIZE]; } } /** --- 19,35 ---- double weightY[]; /* largest weight in each row */ GridBagLayoutInfo () { ! this(GridBagLayout.MAXGRIDSIZE, GridBagLayout.MAXGRIDSIZE); } + GridBagLayoutInfo(int width, int height) { + this.width = width; + this.height = height; + + minWidth = new int[width]; + minHeight = new int[height]; + weightX = new double[width]; + weightY = new double[height]; + } } /** *************** *** 269,275 **** * } * </pre></blockquote><hr> * <p> ! * @version 1.5, 16 Nov 1995 * @author Doug Stein * @see java.awt.GridBagConstraints * @see java.awt.ComponentOrientation --- 276,282 ---- * } * </pre></blockquote><hr> * <p> ! * @version %I%, %G% * @author Doug Stein * @see java.awt.GridBagConstraints * @see java.awt.ComponentOrientation *************** *** 279,286 **** java.io.Serializable { /** ! * The maximum number of grid positions (both horizontally and ! * vertically) that can be laid out by the grid bag layout. */ protected static final int MAXGRIDSIZE = 512; --- 286,294 ---- java.io.Serializable { /** ! * As of 1.5, this field is no longer used. Previously, this was ! * the maximum number of grid positions (both horizontal and ! * vertical) that could be laid out by the grid bag layout. */ protected static final int MAXGRIDSIZE = 512; *************** *** 819,824 **** --- 827,840 ---- return GetLayoutInfo(parent, sizeflag); } + private static final Integer ZERO = new Integer(0); + private static void ensureSize(ArrayList<Integer> arrayList, int size) { + arrayList.ensureCapacity(size); + while (arrayList.size() < size) { + arrayList.add(ZERO); + } + } + /** * This method is obsolete and supplied for backwards * compatability only; new code should call {@link *************** *** 829,844 **** */ protected GridBagLayoutInfo GetLayoutInfo(Container parent, int sizeflag) { synchronized (parent.getTreeLock()) { ! GridBagLayoutInfo r = new GridBagLayoutInfo(); Component comp; GridBagConstraints constraints; Dimension d; Component components[] = parent.getComponents(); int compindex, i, j, k, px, py, pixels_diff, nextSize; int curX, curY, curWidth, curHeight, curRow, curCol; double weight_diff, weight, start, size; int xMax[], yMax[]; /* * Pass #1 --- 845,863 ---- */ protected GridBagLayoutInfo GetLayoutInfo(Container parent, int sizeflag) { synchronized (parent.getTreeLock()) { ! GridBagLayoutInfo r; Component comp; GridBagConstraints constraints; Dimension d; Component components[] = parent.getComponents(); + int layoutWidth, layoutHeight; int compindex, i, j, k, px, py, pixels_diff, nextSize; int curX, curY, curWidth, curHeight, curRow, curCol; double weight_diff, weight, start, size; int xMax[], yMax[]; + ArrayList<Integer> xMaxArray = new ArrayList<Integer>(components.length); + ArrayList<Integer> yMaxArray = new ArrayList<Integer>(components.length); /* * Pass #1 *************** *** 847,856 **** * zero or negative widths and heights). */ ! r.width = r.height = 0; curRow = curCol = -1; - xMax = new int[MAXGRIDSIZE]; - yMax = new int[MAXGRIDSIZE]; for (compindex = 0 ; compindex < components.length ; compindex++) { comp = components[compindex]; --- 866,873 ---- * zero or negative widths and heights). */ ! layoutWidth = layoutHeight = 0; curRow = curCol = -1; for (compindex = 0 ; compindex < components.length ; compindex++) { comp = components[compindex]; *************** *** 878,885 **** } if (curX < 0) { px = 0; ! for (i = curY; i < (curY + curHeight); i++) ! px = Math.max(px, xMax[i]); curX = px - curX - 1; if(curX < 0) --- 895,904 ---- } if (curX < 0) { px = 0; ! ensureSize(xMaxArray, curY + curHeight); ! for (i = curY; i < (curY + curHeight); i++) { ! px = Math.max(px, xMaxArray.get(i).intValue()); ! } curX = px - curX - 1; if(curX < 0) *************** *** 887,894 **** } else if (curY < 0) { py = 0; ! for (i = curX; i < (curX + curWidth); i++) ! py = Math.max(py, yMax[i]); curY = py - curY - 1; if(curY < 0) --- 906,915 ---- } else if (curY < 0) { py = 0; ! ensureSize(yMaxArray, curX + curWidth); ! for (i = curX; i < (curX + curWidth); i++) { ! py = Math.max(py, yMaxArray.get(i).intValue()); ! } curY = py - curY - 1; if(curY < 0) *************** *** 896,907 **** } /* Adjust the grid width and height */ ! for (px = curX + curWidth; r.width < px; r.width++); ! for (py = curY + curHeight; r.height < py; r.height++); ! /* Adjust the xMax and yMax arrays */ ! for (i = curX; i < (curX + curWidth); i++) { yMax[i] = py; } ! for (i = curY; i < (curY + curHeight); i++) { xMax[i] = px; } /* Cache the current slave's size. */ if (sizeflag == PREFERREDSIZE) --- 917,934 ---- } /* Adjust the grid width and height */ ! for (px = curX + curWidth; layoutWidth < px; layoutWidth++); ! for (py = curY + curHeight; layoutHeight < py; layoutHeight++); ! /* Adjust xMaxArray and yMaxArray */ ! ensureSize(yMaxArray, curX + curWidth); ! for (i = curX; i < (curX + curWidth); i++) { ! yMaxArray.set(i, new Integer(py)); ! } ! ensureSize(xMaxArray, curY + curHeight); ! for (i = curY; i < (curY + curHeight); i++) { ! xMaxArray.set(i, new Integer(px)); ! } /* Cache the current slave's size. */ if (sizeflag == PREFERREDSIZE) *************** *** 928,938 **** /* * Apply minimum row/column dimensions */ ! if (columnWidths != null && r.width < columnWidths.length) ! r.width = columnWidths.length; ! if (rowHeights != null && r.height < rowHeights.length) ! r.height = rowHeights.length; /* * Pass #2 * --- 955,970 ---- /* * Apply minimum row/column dimensions */ ! if (columnWidths != null && layoutWidth < columnWidths.length) ! layoutWidth = columnWidths.length; ! if (rowHeights != null && layoutHeight < rowHeights.length) ! layoutHeight = rowHeights.length; + // Now that we know the grid's width and height, create the + // GridBagLayoutInfo. + r = new GridBagLayoutInfo(layoutWidth, layoutHeight); + + /* * Pass #2 * *************** *** 943,950 **** */ curRow = curCol = -1; ! xMax = new int[MAXGRIDSIZE]; ! yMax = new int[MAXGRIDSIZE]; for (compindex = 0 ; compindex < components.length ; compindex++) { comp = components[compindex]; --- 975,982 ---- */ curRow = curCol = -1; ! xMax = new int[layoutHeight]; ! yMax = new int[layoutWidth]; for (compindex = 0 ; compindex < components.length ; compindex++) { comp = components[compindex]; ###@###.### 2003-11-14 *** /tmp/geta17605 14 11:44:43 2005 --- GridBagLayout.java 10 15:35:07 2005 *************** *** 840,846 **** * maximumArrayXIndex and maximumArrayYIndex. */ ! private Point preInitMaximumArraySizes(Container parent){ Component components[] = parent.getComponents(); Component comp; GridBagConstraints constraints; --- 840,846 ---- * maximumArrayXIndex and maximumArrayYIndex. */ ! private long[] preInitMaximumArraySizes(Container parent){ Component components[] = parent.getComponents(); Component comp; GridBagConstraints constraints; *************** *** 848,854 **** int curWidth, curHeight; int preMaximumArrayXIndex = 0; int preMaximumArrayYIndex = 0; ! for (int compId = 0 ; compId < components.length ; compId++) { comp = components[compId]; if (!comp.isVisible()) { --- 848,855 ---- int curWidth, curHeight; int preMaximumArrayXIndex = 0; int preMaximumArrayYIndex = 0; ! long [] returnArray = new long[2]; ! for (int compId = 0 ; compId < components.length ; compId++) { comp = components[compId]; if (!comp.isVisible()) { *************** *** 886,892 **** preMaximumArrayYIndex = Math.max(curX + curWidth, preMaximumArrayYIndex); } //for (components) loop // Must specify index++ to allocate well-working arrays. ! return new Point(preMaximumArrayXIndex, preMaximumArrayYIndex); } //PreInitMaximumSizes /** --- 887,898 ---- preMaximumArrayYIndex = Math.max(curX + curWidth, preMaximumArrayYIndex); } //for (components) loop // Must specify index++ to allocate well-working arrays. ! /* fix for 4623196. ! * now return long array instead of Point ! */ ! returnArray[0] = preMaximumArrayXIndex; ! returnArray[1] = preMaximumArrayYIndex; ! return returnArray; } //PreInitMaximumSizes /** *************** *** 933,942 **** layoutWidth = layoutHeight = 0; curRow = curCol = -1; ! Point p = preInitMaximumArraySizes(parent); ! maximumArrayXIndex = EMPIRICMULTIPLIER*p.x; ! maximumArrayYIndex = EMPIRICMULTIPLIER*p.y; xMaxArray = new int[maximumArrayXIndex]; yMaxArray = new int[maximumArrayYIndex]; --- 939,955 ---- layoutWidth = layoutHeight = 0; curRow = curCol = -1; ! long [] arraySizes = preInitMaximumArraySizes(parent); + /* fix for 4623196. + * If user try to create a very big grid we can + * get NegativeArraySizeException because of integer value + * overflow (EMPIRICMULTIPLIER*gridSize might be more then Integer.MAX_VALUE). + * We need to detect this situation and try to create a + * grid with Integer.MAX_VALUE size instead. + */ + maximumArrayXIndex = (EMPIRICMULTIPLIER * arraySizes[0] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[0]; + maximumArrayYIndex = (EMPIRICMULTIPLIER * arraySizes[1] > Integer.MAX_VALUE )? Integer.MAX_VALUE : EMPIRICMULTIPLIER*(int)arraySizes[1]; xMaxArray = new int[maximumArrayXIndex]; yMaxArray = new int[maximumArrayYIndex]; ###@###.### 2005-03-14 09:02:49 GMT
2005-03-14

EVALUATION Commit to fix in next release (JCK). ###@###.### 2002-01-14 Waiting to see what happens with this test. At this point, it fails at least as far back as 1.3.1. ###@###.### 2003-05-08 Still fails with 1.5b19: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 512 at java.awt.GridBagLayout.GetLayoutInfo(GridBagLayout.java:905) at java.awt.GridBagLayout.getLayoutInfo(GridBagLayout.java:821) at java.awt.GridBagLayout.preferredLayoutSize(GridBagLayout.java:641) at java.awt.Container.preferredSize(Container.java:1544) at java.awt.Container.getPreferredSize(Container.java:1530) at java.awt.Window.pack(Window.java:457) at addLC.main(addLC.java:32) The failing line is: for (i = curX; i < (curX + curWidth); i++) { yMax[i] = py; } ###@###.### 2003-09-15 Fixing 4254022 (PERF: GridBagLayout inefficiency), which has over 30 JDC votes, would also fix this bug in that it wouldn't limit the grid to 512 items. ###@###.### 2003-10-15 After modifying GridBagLayoutInfo to dynamically size its arrays, I run into a java.lang.OutOfMemoryError when running this test. I also tried setting MAXGRIDSIZE to Integer.MAX_VALUE. This immediately fails with: /net/awt-blade/localhome/bchristi/tiger/build/solaris-sparc/bin/java -Xmx3930M addLC Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit I conclude that even if we fix the ArrayIndexOutOfBoundsException, there is no way this test can pass due to memory constraints. Perhaps we need to change the spec to reflect this. ###@###.### 2003-10-17 I got word back from the JCK lead in SPB. It "is not API javadoc responsibility to cover this", so I'm only going to change the doc to state that we no longer use MAXGRIDSIZE. See 4254022. ###@###.### 2003-10-22 Initially this bug filed against AIOOBE inside GridBagLayout. After some fixes in this layout manager we become able to create large grids (bigger then 512 cells). When user tries to create Integer.MAX_VALUE grid he could get integer value overflow and an attempt to create an array with negative size. ###@###.### 2005-03-11 17:28:56 GMT
2005-03-11

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
2004-09-07