# HG changeset patch # User serb # Date 1431529579 -10800 # Node ID 855dbf52e45ddc34791357d7eb515c9ece392c76 # Parent bd693c5b056692cc7ee2879b840cab81c1910ff9 8072775: Tremendous memory usage by JTextArea Reviewed-by: vadim, prr diff -r bd693c5b0566 -r 855dbf52e45d jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java --- a/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java Tue May 12 13:45:49 2015 -0700 +++ b/jdk/src/java.desktop/share/classes/sun/font/StandardTextSource.java Wed May 13 18:06:19 2015 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -33,42 +33,43 @@ import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; -public class StandardTextSource extends TextSource { - char[] chars; - int start; - int len; - int cstart; - int clen; - int level; // assumed all uniform - int flags; // see GlyphVector.java - Font font; - FontRenderContext frc; - CoreMetrics cm; +final class StandardTextSource extends TextSource { + + private final char[] chars; + private final int start; + private final int len; + private final int cstart; + private final int clen; + private final int level; // assumed all uniform + private final int flags; // see GlyphVector.java + private final Font font; + private final FontRenderContext frc; + private final CoreMetrics cm; - /** - * Create a simple implementation of a TextSource. - * - * Chars is an array containing clen chars in the context, in - * logical order, contiguously starting at cstart. Start and len - * represent that portion of the context representing the true - * source; start, like cstart, is relative to the start of the - * character array. - * - * Level is the bidi level (0-63 for the entire context. Flags is - * the layout flags. Font is the font, frc is the render context, - * and lm is the line metrics for the entire source text, but not - * necessarily the context. - */ - public StandardTextSource(char[] chars, - int start, - int len, - int cstart, - int clen, - int level, - int flags, - Font font, - FontRenderContext frc, - CoreMetrics cm) { + /** + * Create a simple implementation of a TextSource. + * + * Chars is an array containing clen chars in the context, in + * logical order, contiguously starting at cstart. Start and len + * represent that portion of the context representing the true + * source; start, like cstart, is relative to the start of the + * character array. + * + * Level is the bidi level (0-63 for the entire context. Flags is + * the layout flags. Font is the font, frc is the render context, + * and lm is the line metrics for the entire source text, but not + * necessarily the context. + */ + StandardTextSource(char[] chars, + int start, + int len, + int cstart, + int clen, + int level, + int flags, + Font font, + FontRenderContext frc, + CoreMetrics cm) { if (chars == null) { throw new IllegalArgumentException("bad chars: null"); } @@ -97,7 +98,7 @@ throw new IllegalArgumentException("bad frc: null"); } - this.chars = chars.clone(); + this.chars = chars; this.start = start; this.len = len; this.cstart = cstart; @@ -115,40 +116,10 @@ } } - /** Create a StandardTextSource whose context is coextensive with the source. */ - public StandardTextSource(char[] chars, - int start, - int len, - int level, - int flags, - Font font, - FontRenderContext frc, - CoreMetrics cm) { - this(chars, start, len, start, len, level, flags, font, frc, cm); - } - - /** Create a StandardTextSource whose context and source are coextensive with the entire char array. */ - public StandardTextSource(char[] chars, - int level, - int flags, - Font font, - FontRenderContext frc) { - this(chars, 0, chars.length, 0, chars.length, level, flags, font, frc, null); - } - - /** Create a StandardTextSource whose context and source are all the text in the String. */ - public StandardTextSource(String str, - int level, - int flags, - Font font, - FontRenderContext frc) { - this(str.toCharArray(), 0, str.length(), 0, str.length(), level, flags, font, frc, null); - } - // TextSource API public char[] getChars() { - return chars.clone(); + return chars; } public int getStart() { diff -r bd693c5b0566 -r 855dbf52e45d jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java --- a/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java Tue May 12 13:45:49 2015 -0700 +++ b/jdk/src/java.desktop/share/classes/sun/font/TextLabelFactory.java Wed May 13 18:06:19 2015 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -48,12 +48,12 @@ * @see TextLayout */ -public class TextLabelFactory { - private FontRenderContext frc; - private char[] text; - private Bidi bidi; +public final class TextLabelFactory { + private final FontRenderContext frc; + private final char[] text; + private final Bidi bidi; private Bidi lineBidi; - private int flags; + private final int flags; private int lineStart; private int lineLimit; diff -r bd693c5b0566 -r 855dbf52e45d jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTextArea/TextViewOOM/TextViewOOM.java Wed May 13 18:06:19 2015 +0300 @@ -0,0 +1,95 @@ +/* + * 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.EventQueue; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/** + * @test + * @bug 8072775 + * @run main/othervm -Xmx80m TextViewOOM + */ +public class TextViewOOM { + + private static JFrame frame; + private static JTextArea ta; + private static final String STRING = "\uDC00\uD802\uDFFF"; + private static final int N = 5000; + + private static void createAndShowGUI() { + frame = new JFrame(); + final JScrollPane jScrollPane1 = new JScrollPane(); + ta = new JTextArea(); + + ta.setEditable(false); + ta.setColumns(20); + ta.setRows(5); + jScrollPane1.setViewportView(ta); + frame.add(ta); + + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(final String[] args) throws Exception { + /* Create and display the form */ + EventQueue.invokeAndWait(TextViewOOM::createAndShowGUI); + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + long mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory before creating the text: "+mem); + final StringBuilder sb = new StringBuilder(N * STRING.length()); + for (int i = 0; i < N; i++) { + sb.append(STRING); + } + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory after creating the text: "+mem); + + EventQueue.invokeAndWait(() -> { + ta.setText(sb.toString()); + for (int i = 0; i < 10; i++) { + System.gc(); + try {Thread.sleep(200);} catch (InterruptedException iex) {} + } + long mem1 = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Memory after setting the text: " + mem1); + }); + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(1000); + } + mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); + System.err.println("Final memory after everything: " + mem); + EventQueue.invokeAndWait(frame::dispose); + } +}