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.
Hi,
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
textArea.getDisplayManager().getScreenLineCount(1)
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.
Hi. See attached patch, for the error in the calculation. I'll have a look at the performance problem.
v1
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
Hi,
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.
v1
Fix in commit r22629. Performance fix follows. See patch #3595304 for progress.