Mercurial > hg > openjdk > jdk8u > jdk
changeset 11782:6042757c329b jdk8u101-b02
Merge
author | asaha |
---|---|
date | Sat, 21 May 2016 23:20:12 -0700 |
parents | 283de90a396e (current diff) f5c7bc7c1f87 (diff) |
children | 544199dbea50 |
files | .hgtags test/javax/swing/JScrollPane/8033000/bug8033000.java |
diffstat | 6 files changed, 367 insertions(+), 185 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Sat May 21 23:15:53 2016 -0700 +++ b/.hgtags Sat May 21 23:20:12 2016 -0700 @@ -544,6 +544,11 @@ 32c49f4a16599e376e4e46bb33c7bcc486e52ff3 jdk8u74-b02 9c828e688240362b6f1b761b619cdaa070462c4e jdk8u74-b31 6968ca30f8fdc9429fcd56187e16f46b215b474b jdk8u74-b32 +02e1209648050922a5a9f2789d9d359795f6f834 jdk8u77-b00 +f08584a0fde9344b0aa4766984266ca68b9a5018 jdk8u77-b01 +1a3e81c05703bb36def80a57681e1692c866f621 jdk8u77-b02 +c44179bce874a97e93ffd7b76a226af417e017a4 jdk8u77-b03 +8c3f4e540348daed7263bae092b0e5f212478b00 jdk8u77-b31 1d4b343084874b1afa1cdd504b9b1e50bab7f121 jdk8u72-b31 7cfd2c51c501df909833aa0fb6e40c50c61621ed jdk8u75-b00 9e00a43602f87930c2318b2567002871ad9c59dd jdk8u75-b01
--- a/src/share/classes/java/math/BigInteger.java Sat May 21 23:15:53 2016 -0700 +++ b/src/share/classes/java/math/BigInteger.java Sat May 21 23:20:12 2016 -0700 @@ -276,6 +276,15 @@ */ private static final int MULTIPLY_SQUARE_THRESHOLD = 20; + /** + * The threshold for using an intrinsic version of + * implMontgomeryXXX to perform Montgomery multiplication. If the + * number of ints in the number is more than this value we do not + * use the intrinsic. + */ + private static final int MONTGOMERY_INTRINSIC_THRESHOLD = 512; + + // Constructors /** @@ -1573,7 +1582,7 @@ * Multiplies int arrays x and y to the specified lengths and places * the result into z. There will be no leading zeros in the resultant array. */ - private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) { + private static int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) { int xstart = xlen - 1; int ystart = ylen - 1; @@ -1897,6 +1906,43 @@ * int array z. The contents of x are not changed. */ private static final int[] squareToLen(int[] x, int len, int[] z) { + int zlen = len << 1; + if (z == null || z.length < zlen) + z = new int[zlen]; + + // Execute checks before calling intrinsified method. + implSquareToLenChecks(x, len, z, zlen); + return implSquareToLen(x, len, z, zlen); + } + + /** + * Parameters validation. + */ + private static void implSquareToLenChecks(int[] x, int len, int[] z, int zlen) throws RuntimeException { + if (len < 1) { + throw new IllegalArgumentException("invalid input length: " + len); + } + if (len > x.length) { + throw new IllegalArgumentException("input length out of bound: " + + len + " > " + x.length); + } + if (len * 2 > z.length) { + throw new IllegalArgumentException("input length out of bound: " + + (len * 2) + " > " + z.length); + } + if (zlen < 1) { + throw new IllegalArgumentException("invalid input length: " + zlen); + } + if (zlen > z.length) { + throw new IllegalArgumentException("input length out of bound: " + + len + " > " + z.length); + } + } + + /** + * Java Runtime may use intrinsic for this method. + */ + private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) { /* * The algorithm used here is adapted from Colin Plumb's C library. * Technique: Consider the partial products in the multiplication @@ -1931,9 +1977,6 @@ * again. The low bit is simply a copy of the low bit of the * input, so it doesn't need special care. */ - int zlen = len << 1; - if (z == null || z.length < zlen) - z = new int[zlen]; // Store the squares, right shifted one bit (i.e., divided by 2) int lastProductLowWord = 0; @@ -2501,6 +2544,75 @@ return (invertResult ? result.modInverse(m) : result); } + // Montgomery multiplication. These are wrappers for + // implMontgomeryXX routines which are expected to be replaced by + // virtual machine intrinsics. We don't use the intrinsics for + // very large operands: MONTGOMERY_INTRINSIC_THRESHOLD should be + // larger than any reasonable crypto key. + private static int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv, + int[] product) { + implMontgomeryMultiplyChecks(a, b, n, len, product); + if (len > MONTGOMERY_INTRINSIC_THRESHOLD) { + // Very long argument: do not use an intrinsic + product = multiplyToLen(a, len, b, len, product); + return montReduce(product, n, len, (int)inv); + } else { + return implMontgomeryMultiply(a, b, n, len, inv, materialize(product, len)); + } + } + private static int[] montgomerySquare(int[] a, int[] n, int len, long inv, + int[] product) { + implMontgomeryMultiplyChecks(a, a, n, len, product); + if (len > MONTGOMERY_INTRINSIC_THRESHOLD) { + // Very long argument: do not use an intrinsic + product = squareToLen(a, len, product); + return montReduce(product, n, len, (int)inv); + } else { + return implMontgomerySquare(a, n, len, inv, materialize(product, len)); + } + } + + // Range-check everything. + private static void implMontgomeryMultiplyChecks + (int[] a, int[] b, int[] n, int len, int[] product) throws RuntimeException { + if (len % 2 != 0) { + throw new IllegalArgumentException("input array length must be even: " + len); + } + + if (len < 1) { + throw new IllegalArgumentException("invalid input length: " + len); + } + + if (len > a.length || + len > b.length || + len > n.length || + (product != null && len > product.length)) { + throw new IllegalArgumentException("input array length out of bound: " + len); + } + } + + // Make sure that the int array z (which is expected to contain + // the result of a Montgomery multiplication) is present and + // sufficiently large. + private static int[] materialize(int[] z, int len) { + if (z == null || z.length < len) + z = new int[len]; + return z; + } + + // These methods are intended to be be replaced by virtual machine + // intrinsics. + private static int[] implMontgomeryMultiply(int[] a, int[] b, int[] n, int len, + long inv, int[] product) { + product = multiplyToLen(a, len, b, len, product); + return montReduce(product, n, len, (int)inv); + } + private static int[] implMontgomerySquare(int[] a, int[] n, int len, + long inv, int[] product) { + product = squareToLen(a, len, product); + return montReduce(product, n, len, (int)inv); + } + static int[] bnExpModThreshTable = {7, 25, 81, 241, 673, 1793, Integer.MAX_VALUE}; // Sentinel @@ -2579,6 +2691,17 @@ int[] mod = z.mag; int modLen = mod.length; + // Make modLen even. It is conventional to use a cryptographic + // modulus that is 512, 768, 1024, or 2048 bits, so this code + // will not normally be executed. However, it is necessary for + // the correct functioning of the HotSpot intrinsics. + if ((modLen & 1) != 0) { + int[] x = new int[modLen + 1]; + System.arraycopy(mod, 0, x, 1, modLen); + mod = x; + modLen++; + } + // Select an appropriate window size int wbits = 0; int ebits = bitLength(exp, exp.length); @@ -2597,8 +2720,10 @@ for (int i=0; i < tblmask; i++) table[i] = new int[modLen]; - // Compute the modular inverse - int inv = -MutableBigInteger.inverseMod32(mod[modLen-1]); + // Compute the modular inverse of the least significant 64-bit + // digit of the modulus + long n0 = (mod[modLen-1] & LONG_MASK) + ((mod[modLen-2] & LONG_MASK) << 32); + long inv = -MutableBigInteger.inverseMod64(n0); // Convert base to Montgomery form int[] a = leftShift(base, base.length, modLen << 5); @@ -2606,6 +2731,8 @@ MutableBigInteger q = new MutableBigInteger(), a2 = new MutableBigInteger(a), b2 = new MutableBigInteger(mod); + b2.normalize(); // MutableBigInteger.divide() assumes that its + // divisor is in normal form. MutableBigInteger r= a2.divide(b2, q); table[0] = r.toIntArray(); @@ -2614,22 +2741,19 @@ if (table[0].length < modLen) { int offset = modLen - table[0].length; int[] t2 = new int[modLen]; - for (int i=0; i < table[0].length; i++) - t2[i+offset] = table[0][i]; + System.arraycopy(table[0], 0, t2, offset, table[0].length); table[0] = t2; } // Set b to the square of the base - int[] b = squareToLen(table[0], modLen, null); - b = montReduce(b, mod, modLen, inv); + int[] b = montgomerySquare(table[0], mod, modLen, inv, null); // Set t to high half of b int[] t = Arrays.copyOf(b, modLen); // Fill in the table with odd powers of the base for (int i=1; i < tblmask; i++) { - int[] prod = multiplyToLen(t, modLen, table[i-1], modLen, null); - table[i] = montReduce(prod, mod, modLen, inv); + table[i] = montgomeryMultiply(t, table[i-1], mod, modLen, inv, null); } // Pre load the window that slides over the exponent @@ -2700,8 +2824,7 @@ isone = false; } else { t = b; - a = multiplyToLen(t, modLen, mult, modLen, a); - a = montReduce(a, mod, modLen, inv); + a = montgomeryMultiply(t, mult, mod, modLen, inv, a); t = a; a = b; b = t; } } @@ -2713,8 +2836,7 @@ // Square the input if (!isone) { t = b; - a = squareToLen(t, modLen, a); - a = montReduce(a, mod, modLen, inv); + a = montgomerySquare(t, mod, modLen, inv, a); t = a; a = b; b = t; } } @@ -2723,7 +2845,7 @@ int[] t2 = new int[2*modLen]; System.arraycopy(b, 0, t2, modLen, modLen); - b = montReduce(t2, mod, modLen, inv); + b = montReduce(t2, mod, modLen, (int)inv); t2 = Arrays.copyOf(b, modLen); @@ -2791,6 +2913,32 @@ * Multiply an array by one word k and add to result, return the carry */ static int mulAdd(int[] out, int[] in, int offset, int len, int k) { + implMulAddCheck(out, in, offset, len, k); + return implMulAdd(out, in, offset, len, k); + } + + /** + * Parameters validation. + */ + private static void implMulAddCheck(int[] out, int[] in, int offset, int len, int k) { + if (len > in.length) { + throw new IllegalArgumentException("input length is out of bound: " + len + " > " + in.length); + } + if (offset < 0) { + throw new IllegalArgumentException("input offset is invalid: " + offset); + } + if (offset > (out.length - 1)) { + throw new IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.length - 1)); + } + if (len > (out.length - offset)) { + throw new IllegalArgumentException("input len is out of bound: " + len + " > " + (out.length - offset)); + } + } + + /** + * Java Runtime may use intrinsic for this method. + */ + private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) { long kLong = k & LONG_MASK; long carry = 0;
--- a/src/share/classes/java/math/MutableBigInteger.java Sat May 21 23:15:53 2016 -0700 +++ b/src/share/classes/java/math/MutableBigInteger.java Sat May 21 23:20:12 2016 -0700 @@ -2065,6 +2065,21 @@ } /** + * Returns the multiplicative inverse of val mod 2^64. Assumes val is odd. + */ + static long inverseMod64(long val) { + // Newton's iteration! + long t = val; + t *= 2 - val*t; + t *= 2 - val*t; + t *= 2 - val*t; + t *= 2 - val*t; + t *= 2 - val*t; + assert(t * val == 1); + return t; + } + + /** * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd. */ static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) {
--- a/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Sat May 21 23:15:53 2016 -0700 +++ b/src/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java Sat May 21 23:20:12 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -870,18 +870,13 @@ int orientation = SwingConstants.VERTICAL; // find which scrollbar to scroll, or return if none - if (toScroll == null || !toScroll.isVisible()) { + if (toScroll == null || !toScroll.isVisible() + || e.isShiftDown()) { toScroll = scrollpane.getHorizontalScrollBar(); if (toScroll == null || !toScroll.isVisible()) { return; } orientation = SwingConstants.HORIZONTAL; - } else if(e.isShiftDown()){ - JScrollBar hScroll = scrollpane.getHorizontalScrollBar(); - if (hScroll != null && hScroll.isVisible()) { - toScroll = hScroll; - orientation = SwingConstants.HORIZONTAL; - } } e.consume();
--- a/test/javax/swing/JScrollPane/8033000/bug8033000.java Sat May 21 23:15:53 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -import java.awt.BorderLayout; -import java.awt.Point; -import java.awt.Robot; -import java.awt.event.KeyEvent; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import sun.awt.OSInfo; - -/** - * @test - * @bug 8033000 - * @author Alexander Scherbatiy - * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI - * @run main bug8033000 - */ -public class bug8033000 { - - private static JScrollPane scrollPane; - private static JTextArea textArea; - private static Point point; - private static final int delta; - - static { - delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; - } - - public static void main(String[] args) throws Exception { - - Robot robot = new Robot(); - robot.setAutoDelay(50); - - SwingUtilities.invokeAndWait(bug8033000::createAndShowGUI); - robot.waitForIdle(); - - SwingUtilities.invokeAndWait(() -> { - Point locationOnScreen = scrollPane.getLocationOnScreen(); - point = new Point( - locationOnScreen.x + scrollPane.getWidth() / 2, - locationOnScreen.y + scrollPane.getHeight() / 2); - }); - - robot.mouseMove(point.x, point.y); - robot.waitForIdle(); - - // vertical scroll bar is enabled - initScrollPane(true, false); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(true); - - // vertical scroll bar is enabled + shift - initScrollPane(true, false); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(true); - - // horizontal scroll bar is enabled - initScrollPane(false, true); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(false); - - // horizontal scroll bar is enabled + shift - initScrollPane(false, true); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(false); - - // both scroll bars are enabled - initScrollPane(true, true); - robot.waitForIdle(); - robot.mouseWheel(delta); - robot.waitForIdle(); - checkScrollPane(true); - - // both scroll bars are enabled + shift - initScrollPane(true, true); - robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_SHIFT); - robot.mouseWheel(delta); - robot.keyRelease(KeyEvent.VK_SHIFT); - robot.waitForIdle(); - checkScrollPane(false); - } - - static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { - SwingUtilities.invokeAndWait(() -> { - scrollPane.getVerticalScrollBar().setValue(0); - scrollPane.getHorizontalScrollBar().setValue(0); - - textArea.setRows(vVisible ? 100 : 1); - textArea.setColumns(hVisible ? 100 : 1); - scrollPane.getVerticalScrollBar().setVisible(vVisible); - scrollPane.getHorizontalScrollBar().setVisible(hVisible); - }); - } - - static void checkScrollPane(boolean verticalScrolled) throws Exception { - SwingUtilities.invokeAndWait(() -> { - - if (verticalScrolled) { - if (scrollPane.getVerticalScrollBar().getValue() == 0 - || scrollPane.getHorizontalScrollBar().getValue() != 0) { - throw new RuntimeException("Wrong vertical scrolling!"); - } - } else { - if (scrollPane.getVerticalScrollBar().getValue() != 0 - || scrollPane.getHorizontalScrollBar().getValue() == 0) { - throw new RuntimeException("Wrong horizontal scrolling!"); - } - } - }); - } - - static void createAndShowGUI() { - JFrame frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setSize(300, 300); - textArea = new JTextArea("Hello World!"); - scrollPane = new JScrollPane(textArea); - JPanel panel = new JPanel(new BorderLayout()); - panel.add(scrollPane, BorderLayout.CENTER); - frame.getContentPane().add(panel); - frame.setVisible(true); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java Sat May 21 23:20:12 2016 -0700 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +import sun.awt.OSInfo; + +/** + * @test + * @bug 8033000 8147994 + * @author Alexander Scherbatiy + * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI + * @run main HorizontalMouseWheelOnShiftPressed + */ +public class HorizontalMouseWheelOnShiftPressed { + + private static JScrollPane scrollPane; + private static JTextArea textArea; + private static Point point; + private static final int delta; + private static JFrame frame; + + static { + delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; + } + + public static void main(String[] args) throws Exception { + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait( + HorizontalMouseWheelOnShiftPressed::createAndShowGUI); + robot.waitForIdle(); + try { + test(robot); + } finally { + frame.dispose(); + } + } + + private static void test(Robot robot) throws Exception { + SwingUtilities.invokeAndWait(() -> { + Point locationOnScreen = scrollPane.getLocationOnScreen(); + point = new Point( + locationOnScreen.x + scrollPane.getWidth() / 2, + locationOnScreen.y + scrollPane.getHeight() / 2); + }); + + robot.mouseMove(point.x, point.y); + robot.waitForIdle(); + + // vertical scroll bar is enabled + initScrollPane(true, false); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(true, false); + + // vertical scroll bar is enabled + shift + initScrollPane(true, false); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, false); + + // horizontal scroll bar is enabled + initScrollPane(false, true); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(false, true); + + // horizontal scroll bar is enabled + shift + initScrollPane(false, true); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, true); + + // both scroll bars are enabled + initScrollPane(true, true); + robot.waitForIdle(); + robot.mouseWheel(delta); + robot.waitForIdle(); + checkScrollPane(true, false); + + // both scroll bars are enabled + shift + initScrollPane(true, true); + robot.waitForIdle(); + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mouseWheel(delta); + robot.keyRelease(KeyEvent.VK_SHIFT); + robot.waitForIdle(); + checkScrollPane(false, true); + } + + static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { + SwingUtilities.invokeAndWait(() -> { + scrollPane.getVerticalScrollBar().setValue(0); + scrollPane.getHorizontalScrollBar().setValue(0); + + textArea.setRows(vVisible ? 100 : 1); + textArea.setColumns(hVisible ? 100 : 1); + scrollPane.getVerticalScrollBar().setVisible(vVisible); + scrollPane.getHorizontalScrollBar().setVisible(hVisible); + }); + } + + static void checkScrollPane(boolean verticalScrolled, + boolean horizontalScrolled) throws Exception { + SwingUtilities.invokeAndWait(() -> { + + if (verticalScrolled) { + if (scrollPane.getVerticalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } else{ + if (scrollPane.getVerticalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } + if (horizontalScrolled) { + if (scrollPane.getHorizontalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } + } else { + if (scrollPane.getHorizontalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } + } + }); + } + + static void createAndShowGUI() { + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + textArea = new JTextArea("Hello World!"); + scrollPane = new JScrollPane(textArea); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(scrollPane, BorderLayout.CENTER); + frame.getContentPane().add(panel); + frame.setVisible(true); + } +}