Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndexOutOfBoundsException in RichText demo #449

Closed
clartaq opened this issue Mar 11, 2017 · 19 comments
Closed

IndexOutOfBoundsException in RichText demo #449

clartaq opened this issue Mar 11, 2017 · 19 comments

Comments

@clartaq
Copy link

clartaq commented Mar 11, 2017

When changing the font of the entire contents of the demo editor pane, an IndexOutOfBounds exception is thrown in the "JavaFX Application Thread".

Steps to reproduce:

  1. Start the RichText demo (from the pre-built jar or building in Gradle).
  2. Paste the README.md file into the demo.
  3. Select All (Ctrl-A)
  4. Select a different [font size or font family from their respective ComboBox] (edited by Jordan)

Environment:

  • Windows 10 Pro, 64-bit
  • RichTextFX 0.6.10
java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

@JordanMartinez
Copy link
Contributor

@clartaq Does this also occur using the 0.7-M3 release?

@JordanMartinez JordanMartinez changed the title IndexOutOfBoundsException in RichText demo [v0.6.10] IndexOutOfBoundsException in RichText demo Mar 12, 2017
@clartaq
Copy link
Author

clartaq commented Mar 12, 2017

The same error occurs when using 0.7-M3, whether I paste the contents of the 0.6.10 README.md or the 0.7-M3 version.

Also, using the new command in the demo to read a file produces an OutOfMemoryError when trying to load either of these files.

@JordanMartinez
Copy link
Contributor

I can't reproduce the bug on my end in either of those versions.

Linux Mint 18.1
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

Also, using the new command in the demo to read a file produces an OutOfMemoryError when trying to load either of these files.

Could you create a new issue specifically for that and with more details as to the issue? I'm not sure which command to which you're referring.

@JordanMartinez
Copy link
Contributor

Can someone else test this on a Windows environment?

@alt-grr
Copy link

alt-grr commented Mar 14, 2017

I can confirm that bug, Windows 10 Enterprise, RichTextFX demo 0.6.10

Stacktrace:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException
        at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136)
        at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:242)
        at com.sun.javafx.scene.control.behavior.ListViewBehavior.lambda$new$177(ListViewBehavior.java:269)
        at javafx.collections.WeakListChangeListener.onChanged(WeakListChangeListener.java:88)
        at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:329)
        at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
        at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:75)
        at javafx.scene.control.MultipleSelectionModelBase.clearAndSelect(MultipleSelectionModelBase.java:378)
        at javafx.scene.control.ListView$ListViewBitSetSelectionModel.clearAndSelect(ListView.java:1403)
        at com.sun.javafx.scene.control.behavior.CellBehaviorBase.simpleSelect(CellBehaviorBase.java:256)
        at com.sun.javafx.scene.control.behavior.CellBehaviorBase.doSelect(CellBehaviorBase.java:220)
        at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:150)
        at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:95)
        at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
        at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
        at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
        at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
        at javafx.event.Event.fireEvent(Event.java:198)
        at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
        at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
        at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
        at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
        at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
        at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
        at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
        at com.sun.glass.ui.View.notifyMouse(View.java:937)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
        at java.lang.Thread.run(Thread.java:745)

Searching for

"com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.subList(ReadOnlyUnbackedObservableList.java:136)"

on Google shows that this is not an uncommon error...

@TomasMikula
Copy link
Member

JDK-8133228

@clartaq
Copy link
Author

clartaq commented Mar 14, 2017

Also happens on Ubuntu.

Environment:

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 16.04.2 LTS
Release:	16.04
Codename:	xenial

$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

$ gradle -v

------------------------------------------------------------
Gradle 3.4.1
------------------------------------------------------------

Build time:   2017-03-03 19:45:41 UTC
Revision:     9eb76efdd3d034dc506c719dac2955efb5ff9a93

Groovy:       2.4.7
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_121 (Oracle Corporation 25.121-b13)
OS:           Linux 4.4.0-66-generic amd64

@JordanMartinez
Copy link
Contributor

Originally, I ran my test through my IDE which AFAIK delegates to Gradle, and never had the issue arise. The issue does appear on my end when I test it via a terminal.

@clartaq
Copy link
Author

clartaq commented Mar 15, 2017

Ah, I never tried it through an IDE, just terminals.

@JordanMartinez
Copy link
Contributor

I think this just proves once again that tests (and demos when debugging them) should be run via terminal, not IDE. I'm sure the error occurs even when run via the IDE; the resulting window just probably didn't display it.

@JordanMartinez JordanMartinez changed the title [v0.6.10] IndexOutOfBoundsException in RichText demo IndexOutOfBoundsException in RichText demo Mar 18, 2017
@JordanMartinez
Copy link
Contributor

Note: this issue also arises when familyCombo, the other comboBox, is used to select a different font family.

@JordanMartinez
Copy link
Contributor

I'm labeling this as both a JDK bug and a regular bug because, although it's caused by the first, we could still rewrite the code to get around it.

@Jugen
Copy link
Collaborator

Jugen commented Feb 11, 2018

I'm getting an occasional IOOB exception being reported using RichTextFX 0.8.2 and decided to look into this bug as part of my research.

So as already noted this is both a JDK bug and a regular bug. The JDK bug only manifests when:

  1. The text contains more than 1 paragraph,
  2. The paragraph break is an empty line (i.e. has no white space character)
  3. The selected text spans a paragraph boundary (i.e. crosses over from 1 paragraph into another), and
  4. Either the font size or family is changed.

The exception is triggered by this line of code inside area.beingUpdatedProperty().addListener:

or familyCombo.getSelectionModel().clearSelection(); depending on if size was changed (for the former) or font family (for the latter).

However this line of code being executed under these conditions is actually the regular bug. This is because it's only supposed to be executed if there is more than one font size (or family) in the selected text. Since the currently selected text has just been set to be a certain font size (or family) there should only be 1 font size (or family) style in the selection - but there isn't !?

The reason for this is because the new font style doesn't get set on or applied to paragraph breaks (i.e. the empty line between paragraphs) due to empty lines being skipped. The relevant line of code primarily responsible for this is:

if(styleSpans.equals(getStyleSpans(from, from + len)) || length() == 0) {
return this;

As can be seen the paragraph is returned as is when the length is zero. If a space is added to the paragraph break then the exception "goes away" because now the style is being applied to the paragraph break. The solution I think is to replace the above code with something like:

if( length() == 0 ) {
   return new Paragraph<>(paragraphStyle, segmentOps, segments, (StyleSpans<S>) styleSpans);
}
if( styleSpans.equals( getStyleSpans( from, from + len ) ) )  { return this; }

@JordanMartinez
Copy link
Contributor

Your proposed solution does resolve the issue. I'm not sure what the implications are (if any) as to what other issues this might produce since I'm not sure what the entire call stack is. Mind submitting another PR for that?

@Jugen
Copy link
Collaborator

Jugen commented Feb 13, 2018

So one implication is that it will cause this test to fail:

// Relates to #345 and #505: calling `EditableStyledDocument::setStyleSpans` when the style spans
// would style an empty paragraph would throw an exception
@Test
public void restylingEmptyParagraphViaStyleSpansWorks() {
TextOps<String, Boolean> segOps = SegmentOps.styledTextOps();
Paragraph<Void, String, Boolean> p = new Paragraph<>(null, segOps, segOps.createEmptySeg(), false);
StyleSpansBuilder<Boolean> builder = new StyleSpansBuilder<>();
builder.add(true, 2);
StyleSpans<Boolean> spans = builder.create();
Paragraph<Void, String, Boolean> restyledP = p.restyle(0, spans);
assertEquals(p, restyledP);
}

specifically on line 35: assertEquals(p, restyledP);

Am I right in saying that if the test is to see whether an exception is thrown under these conditions then the assertion can be removed and the test will still be valid. If so then I can go ahead with the proposed change, modify the above test, and write another to check that styles are being applied to empty paragraphs.

@JordanMartinez
Copy link
Contributor

mm....

I think the assertion should still hold... If one uses getTextStyleForInsertionAt
https://github.com/FXMisc/RichTextFX/blob/master/richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java#L1117-L1124

... then I think the paragraph's style does matter and will produce different results.

@Jugen
Copy link
Collaborator

Jugen commented Feb 13, 2018

Sorry I don't follow your reasoning here ? The proposed change is going to change what getTextStyleForInsertionAt( pos ) returns if pos is the empty line.

Bear in mind that the current behavior is actually incorrect in that if you have selected multiple paragraphs and change the font size for example, and then decide to insert something at one of the paragraph breaks using getTextStyleForInsertionAt then if I'm not mistaken you will get the incorrect style returned. The font size in this case will be what it was before the change and not what that section of the document currently is.

At least that's how I understand it, or did you have something different in mind ?

@JordanMartinez
Copy link
Contributor

Mm... Those are good points. I don't think I fully understood the entirety of the problem, hence, my response.

In response to your original question then, I think that would be a good modification to make.

@JordanMartinez
Copy link
Contributor

Closed by #685

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants