2009-11-18 122 views
0

我正在用我的一個類實現Cloneable,並且我需要爲java.util.LinkedList做一個淺拷貝(是的,只是淺的)。我試着用java.util.LinkedList導致無限循環/ OutOfMemoryError

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是枚舉類型,意外實現Cloneable的和其clone()方法錄如下。位置,restFlag,tripFlag,和持續時間都是原語

public Accidental clone(){ 
    return new Accidental(acType,fltPosition); 

} 

acType是內枚舉類型,fltPosition是是浮子,這些初始化只有兩個字段在偶然的。

當我調用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

而且最近,我已經受夠了LinkedList的在Note.clone的第一線建設()我有類似的問題。即

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)

+2

您如何知道clone()調用是罪魁禍首?請發佈堆棧跟蹤和足夠的正在編寫的類(實現Cloneable的類),以便我們瞭解發生了什麼。 – 2009-11-18 04:49:57

+0

包括整個clone()方法。 – 2009-11-18 04:50:41

+0

你能寫一個小測試用例並重現這個問題嗎?如果是這樣,請在此處發佈。 – 2009-11-18 05:00:32

回答

0

好吧,所以我想通了。我以爲我在做一些導致LinkedList無限循環的事情,但實際發生的是我編寫了一個包含對LinkedList方法調用的無限循環,而且恰恰是當我暫停該線程或系統用完時內存,它是在執行LinkedList方法的過程中。
顯然,那些必須花費更長的時間來執行循環內部的代碼或其他東西。因爲當我查看堆棧跟蹤時總是在LinkedList中,所以我認爲我在某種程度上打破了LinkedList,實際上,我的破解代碼只是簡單地調用LinkedList方法,直到我停止它或它耗盡內存。

0

你檢查內存分配方案的JVM?具體爲-Xms-Xmx。你可能已經填滿了默認分配的所有內存。你可以用

-Xms256m -Xmx1024m 

看看它是否在同一個地方失敗?

+0

我試過了,它仍然凍結。我不確定它現在會耗盡內存,儘管我的猜測是最終會發生。事情是被複制的列表包含非常少的數據(我用調試器驗證了這一點)事實上,在我提到的第二個錯誤的情況下,我正在構建一個空的列表,當它凍結時。我覺得這種手術不應該花費太多的時間和記憶,錯誤或沒有。 – 2009-11-18 06:04:49

+0

哎呀,猜這個斜體不會出現在這裏。好吧。 – 2009-11-18 06:05:49

+0

出於好奇,我讓我暫停的線程繼續,事實上它最終確實耗盡了內存。肯定會出現某種無限循環,我只是無法弄清楚可能導致它的原因。 – 2009-11-18 06:15:44

2

LinkedList :: clone()沒有錯。如果它掛了,那麼你的名單是腐敗的,不知何故形成了一個循環鏈接。這是唯一的相關代碼從java/util/LinkedList.java的exerpt:

for (Entry e = header.next; e != header; e = e.next) 
    clone.add(e.element);

這是用於鏈表::指定者()相同的算法,所以如果克隆()掛起,那麼也應該這樣:

System.out.println(Arrays.toString(myList.toArray()));

如果掛起,你的名單是腐敗的。最有可能的小節將是同步問題。 LinkedList不是線程安全的。嘗試像這樣同步你的聲明:

List<myType> myList = Collections.synchronizedList(new LinkedList<myType>());

+0

我不是手動多線程。這是一個swing應用程序,所以我知道後臺正在進行多線程處理,但我一直認爲我的所有代碼都將在一個線程中執行,而且我不需要處理同步。那是錯的嗎?如果是這樣,那麼調用swing api將導致產生一個新的線程? – 2009-11-18 15:26:46

+0

偶然的是,我從來不想暗示這個問題實際上是在LinkedList中,我知道這是我的錯,但我只是想知道我的代碼如何在LinkedList中導致無限循環,並且您似乎已經回答了這個問題。 – 2009-11-18 15:41:49

+0

我做了開關,但我仍然遇到問題。實際上,想一想,我應該看到了,因爲我在構建* empty * LinkedList時遇到了這個問題。 – 2009-11-18 22:53:36