diff --git a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java b/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java
index babbfaa7b5ffce3083abab1e880e59b9c140ba50..e20ac44d79a0f3a9211a848cfaaca947d2d2ffcc 100644
--- a/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java
+++ b/components/net/sf/briar/transport/IncomingErrorCorrectionLayerImpl.java
@@ -1,9 +1,11 @@
 package net.sf.briar.transport;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import net.sf.briar.api.FormatException;
 import net.sf.briar.api.transport.Segment;
@@ -15,6 +17,7 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
 	private final int n, k;
 	private final Map<Long, Integer> discardCounts;
 	private final Map<Long, Segment[]> segmentSets;
+	private final ArrayList<Segment> freeSegments;
 
 	IncomingErrorCorrectionLayerImpl(IncomingEncryptionLayer in,
 			ErasureDecoder decoder, int n, int k) {
@@ -24,24 +27,37 @@ class IncomingErrorCorrectionLayerImpl implements IncomingErrorCorrectionLayer {
 		this.k = k;
 		discardCounts = new HashMap<Long, Integer>();
 		segmentSets = new HashMap<Long, Segment[]>();
+		freeSegments = new ArrayList<Segment>();
 	}
 
 	public boolean readFrame(Frame f, FrameWindow window) throws IOException,
 	InvalidDataException {
 		// Free any segment sets that have been removed from the window
-		Iterator<Long> it = segmentSets.keySet().iterator();
-		while(it.hasNext()) if(!window.contains(it.next())) it.remove();
+		Iterator<Entry<Long, Segment[]>> it = segmentSets.entrySet().iterator();
+		while(it.hasNext()) {
+			Entry<Long, Segment[]> e = it.next();
+			if(!window.contains(e.getKey())) {
+				it.remove();
+				for(Segment s : e.getValue()) if(s != null) freeSegments.add(s);
+			}
+		}
 		// Free any discard counts that are no longer too high for the window
 		Iterator<Long> it1 = discardCounts.keySet().iterator();
 		while(it1.hasNext()) if(!window.isTooHigh(it1.next())) it1.remove();
-		// FIXME: Unnecessary allocation
-		Segment s = new SegmentImpl();
+		// Grab a free segment, or allocate one if necessary
+		Segment s;
+		int free = freeSegments.size();
+		if(free == 0) s = new SegmentImpl();
+		else s = freeSegments.remove(free - 1);
 		// Read segments until a frame can be decoded
 		while(true) {
 			// Read segments until a segment in the window is returned
 			long frameNumber;
 			while(true) {
-				if(!in.readSegment(s)) return false;
+				if(!in.readSegment(s)) {
+					freeSegments.add(s);
+					return false;
+				}
 				frameNumber = s.getSegmentNumber() / n;
 				if(window.contains(frameNumber)) break;
 				if(window.isTooHigh(frameNumber)) countDiscard(frameNumber);