Exception in thread "main" java.lang.OutOfMemoryError: Java

Quando eu chamo: System.out.println(" Valores: " + l );
na classe test o programa não para mais…
Alguém me pode ajudar ?
O programa fica ali preso nos métodos hasNext e next da class LinkedIterator .

package SegundoTrabalhoSegundaParte;

import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.NoSuchElementException;

@SuppressWarnings("unchecked")
public class DLinkedCollection extends AbstractCollection {
	// Nó da lista duplamente ligada
	private class Node {
		private Object element = null; // Referencia para os dados
		private Node next;             // Referencia para o nó seguinte
		private Node prev;             // Referencia para o nó anterior
		private Node(Object o, Node n, Node p) { element = o; next = n; prev = p; }
		private Node() { next = prev = this; }

	}

	// Iterador da colecção implementada com uma lista duplamente ligada
	private class LinkedIterator implements Iterator {
		//implementar
		private Node current= dummy.next;  //+
		 
		private Node beforeLast =dummy.prev;
		
		DLinkedCollection owner;

		public boolean hasNext() {	//+
			
			if(current!=null){
				return (current.next != null); //+
			}
				return false;	
	
		}

		


		//implementar(done)
		public Object next() {			//+
			if (!hasNext()) throw new NoSuchElementException();
			
			current = current.next;		
			
			return current.element;		//+
		
		}

		

		//implementar(done)
		public void remove() {	//+
			if (beforeLast == null) 
				throw new IllegalStateException();
			 //+
			removeNode(beforeLast);	//+
			beforeLast =null;	//+
		
			}
		// Implementar (done)
	}

	Node dummy = new Node();
	
	

	int size = 0;

	public int size() {	return size; }

	@SuppressWarnings("unchecked")
	public Iterator iterator() { return new LinkedIterator(); }

	// Adiciona à lista um novo nó depois do nó passado como parâmetro
	private void addNode(Node prev, Object element ) {
		// Implementar (done but )
		Node novo = new Node();
		if (prev == null || novo == null) 
			throw new IllegalStateException();
		novo.next = prev.next;
		novo.prev = prev;
		novo.next.prev = novo;
		novo.prev.next=novo ;
		novo.element=element;
		++size;
	}

	// Remove da lista o nó passado como parâmetro
	private void removeNode( Node rem ) {
		dummy = rem;
		dummy.prev.next=dummy.next;
		dummy.next.prev=dummy.prev;
		--size;
	}


	public boolean add(Object element){ 
		addNode(dummy.prev, element); return true; 
	}
	public void addFirst(Object element) { addNode(dummy, element);	}
	public void addLast(Object element)  { addNode(dummy.prev, element); }
	public void removeFirst() {  removeNode(dummy.next); }
	public void removeLast() {  removeNode(dummy.prev); }
	public Object getFirst() {
		if ( size == 0 ) throw new NoSuchElementException();
		return dummy.next.element;
	}
	public Object getLast()  {  
		if ( size == 0 ) throw new NoSuchElementException();
		return dummy.prev.element; 
	}
}
package SegundoTrabalhoSegundaParte;



public class Test {

	public static void escrever( DLinkedCollection l ) {
		if ( l.isEmpty() ) System.out.println("Lista vazia");
		else {
			System.out.println("List" );
			System.out.println("  Size: " + l.size() );
			System.out.println("  First: " + l.getFirst() );
			System.out.println("  Last: " + l.getLast() );
			System.out.println("  Valores: " + l );
		}
	}
	public static void main(String[] args) {
		DLinkedCollection l = new DLinkedCollection();

		for (int i= 1; i < 5; ++ i)  
			l.add( new Integer(i));
		l.addFirst( new Integer(0) );

		escrever( l );
		for (int i= 4; i <= 5; ++ i) 
			if ( l.contains(i)) System.out.println("A lista contém o valor " + i);
			else System.out.println("A lista não contém o valor " + i);
		l.remove(new Integer(1));
		System.out.println("Depois de remover o valor 1 " + l);
		l.removeFirst();
		System.out.println("Depois de remover o primeiro " + l);
		l.removeLast();
		System.out.println("Depois de remover o ultimo " + l);
	}

}