#383 Fix for Bug #1229377 - copy/paste memory usage

closed-accepted
None
5
2011-10-17
2011-02-18
Evan Wright
No

This patch adds a cap to the size of a HistoryModel, so that when copying huge amounts of text, the clipboard history model does not use up all available heap space. It also limits the size of the previews in the PasteFromListDialog, because adding 5 megabytes of text to a JTextArea is a _bad_ idea. This should fix bug #1229377 - jEdit's oldest open severe bug (from 2005)!.

Discussion

  • Evan Wright
    Evan Wright
    2011-02-18

     
    Attachments
  • Alan Ezust
    Alan Ezust
    2011-08-30

    • assigned_to: nobody --> kpouer
     
  • Hi, I don't see the problem.
    It is trying to show a too long String in the TextArea of the dialog ?

    Anyway I had this exception
    java.lang.ClassCastException: org.gjt.sp.jedit.buffer.UndoManager$RemovedContent cannot be cast to java.lang.String
    at org.gjt.sp.jedit.gui.PasteFromListDialog.getSelectedClipText(PasteFromListDialog.java:156)
    at org.gjt.sp.jedit.gui.PasteFromListDialog.showClipText(PasteFromListDialog.java:189)
    at org.gjt.sp.jedit.gui.PasteFromListDialog.access$200(PasteFromListDialog.java:35)
    at org.gjt.sp.jedit.gui.PasteFromListDialog$ListHandler.valueChanged(PasteFromListDialog.java:295)
    at javax.swing.JList.fireSelectionValueChanged(JList.java:1798)
    at javax.swing.JList$ListSelectionHandler.valueChanged(JList.java:1812)
    at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:184)
    at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:164)
    at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:211)
    at javax.swing.DefaultListSelectionModel.changeSelection(DefaultListSelectionModel.java:405)
    at javax.swing.DefaultListSelectionModel.changeSelection(DefaultListSelectionModel.java:415)
    at javax.swing.DefaultListSelectionModel.setSelectionInterval(DefaultListSelectionModel.java:459)
    at javax.swing.JList.setSelectedIndex(JList.java:2212)
    at org.gjt.sp.jedit.gui.PasteFromListDialog.<init>(PasteFromListDialog.java:88)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at org.gjt.sp.jedit.bsh.Reflect.constructObject(Reflect.java:620)
    at org.gjt.sp.jedit.bsh.BSHAllocationExpression.constructObject(BSHAllocationExpression.java:123)
    at org.gjt.sp.jedit.bsh.BSHAllocationExpression.objectAllocation(BSHAllocationExpression.java:114)
    at org.gjt.sp.jedit.bsh.BSHAllocationExpression.eval(BSHAllocationExpression.java:62)
    at org.gjt.sp.jedit.bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:102)
    at org.gjt.sp.jedit.bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:47)
    at org.gjt.sp.jedit.bsh.BSHBlock.evalBlock(BSHBlock.java:130)
    at org.gjt.sp.jedit.bsh.BSHBlock.eval(BSHBlock.java:80)
    at org.gjt.sp.jedit.bsh.BshMethod.invokeImpl(BshMethod.java:362)
    at org.gjt.sp.jedit.bsh.BshMethod.invoke(BshMethod.java:258)
    at org.gjt.sp.jedit.bsh.BshMethod.invoke(BshMethod.java:186)
    at org.gjt.sp.jedit.BeanShellFacade.runCachedBlock(BeanShellFacade.java:225)
    at org.gjt.sp.jedit.BeanShell.runCachedBlock(BeanShell.java:423)
    at org.gjt.sp.jedit.BeanShellAction.invoke(BeanShellAction.java:73)
    at org.gjt.sp.jedit.gui.InputHandler.invokeAction(InputHandler.java:342)
    at org.gjt.sp.jedit.gui.ActionBar$1.run(ActionBar.java:207)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:675)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

     
  • Evan Wright
    Evan Wright
    2011-09-02

    You are correct about the exception. The cast to String should be a call to toString() in order to work with deletions. I've uploaded a new version of the patch that corrects this.

    Here are the problems that this patch fixes:

    1) Copy a huge amount of text (I used a 5MB file), open the "Paste Previous..." dialog and close it, and suddenly memory usage is permanently very high, and additional copy operations (even small ones) are permanently slow. This is because the JList from the dialog keeps getting updated even after the dialog is closed, and this takes some time (see #3).

    2) Copy a few different huge chunks of text, and you can easily get the copy history to take up all available memory. This is because while the number of items in the history is capped, the total size is not.

    3) Copy a huge chunk of text and then a small one, open the "Paste Previous.." dialog, and navigate to the big chunk. On my machine, it takes a couple of seconds to switch, and it's very easy to get "out of memory" exceptions or even crash. This is because sticking 5MB in a JTextArea is very slow and very memory-hungry.

     
  • Evan Wright
    Evan Wright
    2011-09-02

    correct a bug in the previous version

     
    Attachments
  • Thanks, I will not be able to review it until next week

     
    • status: open --> closed-accepted
     
  • applied in trunk