diff --git a/src/java.desktop/share/classes/javax/swing/text/StringContent.java b/src/java.desktop/share/classes/javax/swing/text/StringContent.java index 562b336c77056..1ce375fa3ab9b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/StringContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/StringContent.java @@ -27,6 +27,7 @@ import java.util.Vector; import java.io.Serializable; import javax.swing.undo.*; +import java.lang.ref.WeakReference; /** * An implementation of the AbstractDocument.Content interface that is @@ -227,7 +228,7 @@ synchronized void updateMarksForInsert(int offset, int length) { int n = marks.size(); for (int i = 0; i < n; i++) { PosRec mark = marks.elementAt(i); - if (mark.unused) { + if (mark.get() == null) { // this record is no longer used, get rid of it marks.removeElementAt(i); i -= 1; @@ -242,7 +243,7 @@ synchronized void updateMarksForRemove(int offset, int length) { int n = marks.size(); for (int i = 0; i < n; i++) { PosRec mark = marks.elementAt(i); - if (mark.unused) { + if (mark.get() == null) { // this record is no longer used, get rid of it marks.removeElementAt(i); i -= 1; @@ -278,7 +279,7 @@ protected Vector getPositionsInRange(Vector v, int offset, Vector placeIn = (v == null) ? new Vector() : v; for (int i = 0; i < n; i++) { PosRec mark = marks.elementAt(i); - if (mark.unused) { + if (mark.get() == null) { // this record is no longer used, get rid of it marks.removeElementAt(i); i -= 1; @@ -303,7 +304,7 @@ protected void updateUndoPositions(Vector positions) { for(int counter = positions.size() - 1; counter >= 0; counter--) { UndoPosRef ref = (UndoPosRef) positions.elementAt(counter); // Check if the Position is still valid. - if(ref.rec.unused) { + if(ref.rec.get() == null) { positions.removeElementAt(counter); } else @@ -323,26 +324,20 @@ protected void updateUndoPositions(Vector positions) { * it.... the update table holds only a reference * to this grungy thing. */ - static final class PosRec { + static final class PosRec extends WeakReference { - PosRec(int offset) { + PosRec(int offset, StickyPosition position) { + super(position); this.offset = offset; } int offset; - boolean unused; } - /** - * This really wants to be a weak reference but - * in 1.1 we don't have a 100% pure solution for - * this... so this class tries to hack a solution - * to causing the marks to be collected. - */ final class StickyPosition implements Position { StickyPosition(int offset) { - rec = new PosRec(offset); + rec = new PosRec(offset, this); marks.addElement(rec); } @@ -350,13 +345,6 @@ public int getOffset() { return rec.offset; } - @SuppressWarnings("removal") - protected void finalize() throws Throwable { - // schedule the record to be removed later - // on another thread. - rec.unused = true; - } - public String toString() { return Integer.toString(getOffset()); } diff --git a/test/jdk/javax/swing/text/AbstractDocument/StringContentPositionTest.java b/test/jdk/javax/swing/text/AbstractDocument/StringContentPositionTest.java new file mode 100644 index 0000000000000..c535c4819e6fc --- /dev/null +++ b/test/jdk/javax/swing/text/AbstractDocument/StringContentPositionTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, 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 javax.swing.text.BadLocationException; +import javax.swing.text.Position; +import javax.swing.text.StringContent; + +/* + * @test + * @summary test that StringContent Position APIs behave as expected. + */ + +public class StringContentPositionTest { + + static final int SIZE = 20; + static final String TEXT = "hello"; + static final int LEN = TEXT.length(); + static final StringContent SC = new StringContent(); + + public static void main(String[] args) throws BadLocationException { + + for (int i = 0; i < 1000; i++) { + test(); + System.gc(); + } + } + + static void test() throws BadLocationException { + + Position[] positions = new Position[SIZE]; + + for (int i = 0; i < SIZE; i++) { + SC.insertString(0, TEXT); + positions[i] = SC.createPosition(LEN); + } + for (int i = 0; i < SIZE; i++) { + int expected = ((SIZE - i) * LEN); + if (positions[i].getOffset() != expected) { + throw new RuntimeException("insert: Bad offset i=" + i + " off=" + positions[i].getOffset()); + } + } + SC.remove(0, SIZE * LEN); + for (int i = 0; i < SIZE; i++) { + if (positions[i].getOffset() != 0) { + throw new RuntimeException("remove: Bad offset i=" + i + " off=" + positions[i].getOffset()); + } + } + } +}