#3758 Null pointer exception and loss of text in text area

Dale Anson

This is probably an edge case, but it's pretty easy to reproduce. I spent a little time looking into a fix, but didn't have any luck.

jEdit from svn, revision 22502. Here's the exception:

6:00:50 PM [AWT-EventQueue-0] [error] EditBus: Exception while sending message on EditBus:
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: java.lang.NullPointerException
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.scrollTo(TextArea.java:856)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.scrollToCaret(TextArea.java:712)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea._finishCaretUpdate(TextArea.java:5116)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.finishCaretUpdate(TextArea.java:5301)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.moveCaretPosition(TextArea.java:2281)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.moveCaretPosition(TextArea.java:2248)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.textarea.TextArea.setCaretPosition(TextArea.java:2217)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.EditPane.loadCaretInfo(EditPane.java:405)
6:00:50 PM [AWT-EventQueue-0] [error] EditBus: at org.gjt.sp.jedit.EditPane.handleBufferUpdate(EditPane.java:1144)

At line 856 in TextArea.java, the Point shouldn't be null but some times is. This might be a timing problem, which is why it doesn't happen except in odd cases.

To reproduce:

1. open jEdit
2. create a new empty buffer, txt mode, soft wrap on
3. go to http://www.piday.org/million.php
4. copy the million digits
5. paste them into the new buffer
6. hypersearch for some string of numbers that will return a result
7. click on the hypersearch result
8. see the text area go completely blank, see the above stack trace in the activity log.


  • Thomas Meyer
    Thomas Meyer


    I guess the problem is, that this test case produces too many screen lines for the ScreenLineManager. the short values wraps into negativ:

    /** This array contains the screen line count for each physical line. */
    private short[] screenLines;

    ScreenLineManager.setScreenLineCount(int line, int count) tries to check this, but fails to do correctly. (the value is set to Short.MAX_VALUE, but the calculation in the last line is casted again to short and results in a negative value).

    I guess this method should log this error in the log and not silently ignore it as its done now.

    Should I change ScreenLineManager to operate with intergers internally?

  • Hi, I tried it, I don't have the exception anymore.
    But I'm not sure to understand something:
    I tried to replace short by integer
    and the result is 18182 which is smaller than Short.MAX_VALUE, do you think the failure happens during calculation ?
    Anyway replacing short by int fixes the exception but I don't think it is enough.
    After doing this, jEdit becomes really unresponsive for me and I have a powerful computer (i7 2600)
    So it fixes the bug but it is still impossible to use jEdit with this kind of files.

  • Thomas Meyer
    Thomas Meyer

    Hi. See attached patch, for the error in the calculation. I'll have a look at the performance problem.

  • Thomas Meyer
    Thomas Meyer

    Offending stack trace seems to be:
    Thread [AWT-EventQueue-0] (Ausgesetzt (Unterbrechungspunkt bei Zeile 597 in Chunk))
    Eigner von: TokenMarker ID
    Chunk.layoutGlyphVector(Font, FontRenderContext, char[], int, int) Zeile: 597
    Chunk.layoutGlyphs(Font, FontRenderContext, char[], int, int) Zeile: 635
    Chunk.init(Segment, TabExpander, float, FontRenderContext, int) Zeile: 457
    DisplayTokenHandler.initChunk(Chunk, float, Segment) Zeile: 181
    DisplayTokenHandler.initChunks(Chunk, Segment) Zeile: 190
    DisplayTokenHandler.makeScreenLine(Segment) Zeile: 398
    DisplayTokenHandler.handleToken(Segment, byte, int, int, TokenMarker$LineContext) Zeile: 102
    TokenMarker.markTokens(TokenMarker$LineContext, TokenHandler, Segment) Zeile: 252
    Buffer.markTokens(Segment, TokenMarker$LineContext, TokenHandler) Zeile: 1708
    Buffer(JEditBuffer).markTokens(int, TokenHandler) Zeile: 1370
    ChunkCache.lineToChunkList(int, List<Chunk>) Zeile: 789
    ChunkCache.updateChunksUpTo(int) Zeile: 671
    ChunkCache.getLineInfo(int) Zeile: 256
    JEditTextArea(TextArea).recalculateLastPhysicalLine() Zeile: 5708
    DisplayManager.notifyScreenLineChanges() Zeile: 536
    DisplayManager.setFirstLine(int, int) Zeile: 579
    JEditTextArea(TextArea).setFirstLine(int) Zeile: 549
    TextArea$AdjustHandler.adjustmentValueChanged(AdjustmentEvent) Zeile: 6547
    JScrollBar.fireAdjustmentValueChanged(int, int, int, boolean) Zeile: 691
    JScrollBar.access$100(JScrollBar, int, int, int, boolean) Zeile: 81
    JScrollBar$ModelListener.stateChanged(ChangeEvent) Zeile: 713
    DefaultBoundedRangeModel.fireStateChanged() Zeile: 364
    DefaultBoundedRangeModel.setRangeProperties(int, int, int, int, boolean) Zeile: 302
    DefaultBoundedRangeModel.setValue(int) Zeile: 168
    JScrollBar.setValue(int) Zeile: 463
    BasicScrollBarUI$TrackListener.setValueFrom(MouseEvent) Zeile: 1253
    BasicScrollBarUI$TrackListener.mouseDragged(MouseEvent) Zeile: 1195
    JScrollBar(Component).processMouseMotionEvent(MouseEvent) Zeile: 6553
    JScrollBar(JComponent).processMouseMotionEvent(MouseEvent) Zeile: 3330
    JScrollBar(Component).processEvent(AWTEvent) Zeile: 6274
    JScrollBar(Container).processEvent(AWTEvent) Zeile: 2229
    JScrollBar(Component).dispatchEventImpl(AWTEvent) Zeile: 4861
    JScrollBar(Container).dispatchEventImpl(AWTEvent) Zeile: 2287
    JScrollBar(Component).dispatchEvent(AWTEvent) Zeile: 4687
    LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) Zeile: 4832
    LightweightDispatcher.processMouseEvent(MouseEvent) Zeile: 4509
    LightweightDispatcher.dispatchEvent(AWTEvent) Zeile: 4422
    View(Container).dispatchEventImpl(AWTEvent) Zeile: 2273
    View(Window).dispatchEventImpl(AWTEvent) Zeile: 2719
    View(Component).dispatchEvent(AWTEvent) Zeile: 4687
    EventQueue.dispatchEventImpl(AWTEvent, Object) Zeile: 723
    EventQueue.access$200(EventQueue, AWTEvent, Object) Zeile: 103
    EventQueue$3.run() Zeile: 682
    EventQueue$3.run() Zeile: 680
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) Zeile: nicht verfügbar [native Methode]
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) Zeile: 76
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext) Zeile: 87
    EventQueue$4.run() Zeile: 696
    EventQueue$4.run() Zeile: 694
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) Zeile: nicht verfügbar [native Methode]
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) Zeile: 76
    EventQueue.dispatchEvent(AWTEvent) Zeile: 693
    EventDispatchThread.pumpOneEventForFilters(int) Zeile: 244
    EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) Zeile: 163
    EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) Zeile: 151
    EventDispatchThread.pumpEvents(int, Conditional) Zeile: 147
    EventDispatchThread.pumpEvents(Conditional) Zeile: 139
    EventDispatchThread.run() Zeile: 97

  • Thomas Meyer
    Thomas Meyer


    the performance problem occurs in the org.gjt.sp.jedit.textarea.ChunkCache.updateChunksUpTo(int) - This method tokenizes the physical line with each scroll attempt. regardless if the physical line has not changed, but only the screen lines have changed, like in the case for the very long line of one million digits of PI.

    Attached patch fixes the problem somehow and checks the current physical line. This is not a good solution of the problem, and fixes not the real problem:
    A better fix would be to change the Tokenizer so, that it only tokenizes the visible part of the physical line...

    feedback is welcome.

  • Thomas Meyer
    Thomas Meyer

    Fix in commit r22629. Performance fix follows. See patch #3595304 for progress.

  • Thomas Meyer
    Thomas Meyer

    • status: open --> closed-fixed