我正在使用我的一个类实现 Cloneable,并且我需要制作 java.util.LinkedList 的浅拷贝(是的,只是浅表)来执行此操作。我尝试使用
myList.clone() //myList is a java.util.LinkedList<myType>
但这导致我的程序停止,所以我转而使用复制构造函数:
new LinkedList<myType>(myList)
但它仍然挂起。现在,这只发生在作为枚举的 myType 上,但现在我对非枚举类型遇到了同样的错误,尽管现在我认为该类型具有内部枚举类型。 Sun 的 jdk 1.6 和 openjdk 1.6 上都发生过这种情况。我确信我做错了什么,但我不知道我会做什么会破坏 LinkedList。它不会抛出异常,直到它最终耗尽内存(通常我会在这种情况发生之前杀死它)。不管怎样,有什么想法可能导致这个问题吗?
这是克隆方法:
public Note clone(){
List<Accidental> retAcc=new LinkedList<Accidental>();
for(Accidental acc:accidentals)retAcc.add(acc.clone());
return new Note(retAcc,position,restFlag,new LinkedList<TieType>(beginTies),new LinkedList<TieType>(endTies),tripFlag,duration);
}
TieType 是一个枚举类型,Accidental 实现了 Cloneable,其 clone() 方法如下所示。 position、restFlag、tripFlag 和uration 都是原语
public Accidental clone(){
return new Accidental(acType,fltPosition);
}
acType是一个内部枚举类型,fltPosition是一个float,它们初始化了唯一的两个字段。
当我调用 LinkedList 复制构造函数时,问题发生在 Note.clone() 方法的最后一行。这曾经是对 LinkedList.clone 的调用,但我更改了它以试图避免此问题。这是此错误的堆栈跟踪(这里没有错误,因为我在线程卡住时挂起线程,而不是等待它耗尽内存,但如您所见,它位于 LinkedList 副本的中间构造函数)
LinkedList.(Collection) line: 115
Note.clone() line: 86
Note.simplify(int) line: 98
Note.split(int, List, List) line: 179
ManagedPart$Measure.adjustRemaining(int) line: 378 ManagedPart$Measure.add(Note) line: 349
ManagedPart$Measure.access$1(ManagedPart$Measure, Note) line: 345
ManagedPart.addNote(Note) line: 216
PartEditor$EditPanel$3.actionPerformed(ActionEvent) line: 104
JButton(AbstractButton).fireActionPerformed(ActionEvent) line: 2012
AbstractButton$Handler.actionPerformed(ActionEvent) line: 2335 DefaultButtonModel.fireActionPerformed(ActionEvent) line: 404
DefaultButtonModel.setPressed(boolean) line: 259
BasicButtonListener.mouseReleased(MouseEvent) line: 253
JButton(Component).processMouseEvent(MouseEvent) line: 6108
JButton(JComponent).processMouseEvent(MouseEvent) line: 3276
JButton(Component).processEvent(AWTEvent) line: 5873
JButton(Container).processEvent(AWTEvent) line: 2105
JButton(Component).dispatchEventImpl(AWTEvent) line: 4469
JButton(Container).dispatchEventImpl(AWTEvent) line: 2163
JButton(Component).dispatchEvent(AWTEvent) line: 4295
LightweightDispatcher.retargetMouseEvent(Component, int, MouseEvent) line: 4461
LightweightDispatcher.processMouseEvent(MouseEvent) line: 4125 LightweightDispatcher.dispatchEvent(AWTEvent) line: 4055
MusedDesktopClient(Container).dispatchEventImpl(AWTEvent) line: 2149
MusedDesktopClient(Window).dispatchEventImpl(AWTEvent) line: 2478
MusedDesktopClient(Component).dispatchEvent(AWTEvent) line: 4295
EventQueue.dispatchEvent(AWTEvent) line: 604
EventDispatchThread.pumpOneEventForFilters(int) line: 275
EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 200
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 190
EventDispatchThread.pumpEvents(int, Conditional) line: 185 EventDispatchThread.pumpEvents(Conditional) line: 177
EventDispatchThread.run() line: 138
最近,我在 Note.clone() i 的第一行中构建 LinkedList 时也遇到了类似的问题。 e.
List<Accidental> retAcc=new LinkedList<Accidental>();
这是堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space at java.util.LinkedList.(LinkedList.java:95) at com.mused.util.noteMgmt.Note.clone(Note.java:84) at com.mused.util.noteMgmt.Note.simplify(Note.java:98) at com.mused.util.noteMgmt.Note.split(Note.java:179) at com.mused.util.noteMgmt.ManagedPart$Measure.adjustRemaining(ManagedPart.java:378) at com.mused.util.noteMgmt.ManagedPart$Measure.insert(ManagedPart.java:335) at com.mused.util.noteMgmt.ManagedPart.insertNote(ManagedPart.java:223) at com.mused.gui.editor.PartEditor.currentIndexChanged(PartEditor.java:161) at com.mused.gui.NoteViewer.fireIndexChangeEvent(NoteViewer.java:178) at com.mused.gui.NoteViewer.setCurrentIndex(NoteViewer.java:417) at com.mused.gui.NoteViewer.updateSelected(NoteViewer.java:627) at com.mused.gui.NoteViewer.mouseMoved(NoteViewer.java:725) at java.awt.Component.processMouseMotionEvent(Component.java:6153) at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:3294) at java.awt.Component.processEvent(Component.java:5877) at java.awt.Container.processEvent(Container.java:2105) at java.awt.Component.dispatchEventImpl(Component.java:4469) at java.awt.Container.dispatchEventImpl(Container.java:2163) at java.awt.Component.dispatchEvent(Component.java:4295) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4461) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4138) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4055) at java.awt.Container.dispatchEventImpl(Container.java:2149) at java.awt.Window.dispatchEventImpl(Window.java:2478) at java.awt.Component.dispatchEvent(Component.java:4295) at java.awt.EventQueue.dispatchEvent(EventQueue.java:604) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177) at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
最佳答案
LinkedList::clone() 没有任何问题。如果它挂起,那么您的列表已损坏,以某种方式形成了循环链接。这是 java/util/LinkedList.java 中唯一相关代码的摘录:
for (Entry e = header.next; e != header; e = e.next)
clone.add(e.element);
这与 LinkedList::toArray() 使用的算法相同,因此如果 clone() 挂起,那么也应该这样:
System.out.println(Arrays.toString(myList.toArray()));
如果挂起,则您的列表已损坏。最有可能的罪魁祸首是同步问题。 LinkedList 不是线程安全的。尝试像这样同步您的声明:
List<myType> myList = Collections.synchronizedList(new LinkedList<myType>());
关于java.util.LinkedList 导致无限循环/OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1753694/