O problema basicamente é o seguinte: quando você envia algo via ObjectOutputStream, o objeto ObjectOutputStream cria uma estrutura de dados interna contendo TODOS os objetos que já foram enviados.
Isso é porque você pode por exemplo enviar algum objeto que tenha referências a objetos que já foram enviados - então ele não precisa enviar isso de novo, não?
E do outro lado, o ObjectInputStream lê os dados recebidos, e também tem uma estrutura de dados interna contendo TODOS os objetos que já foram recebidos. Isso é para poder remontar o objeto, exatamente da forma que você estava esperando.
O problema é que isso pode acabar fritando os dois lados, porque você normalmente não faz referências a objetos já enviados em seus objetos. O que ocorre é que os dois lados acabam esgotando a memória do Java porque os objetos nunca são removidos.
Para quebrar esse galho, existe um método em ObjectOutputStream chamado “reset” (se não me engano). Ele faz o seguinte:
- Limpa essa estrutura de dados que contém os objetos já enviados;
- Envia um comando especial ao ObjectInputStream para limpar a estrutura de dados que contém os objetos já recebidos.
Só que antes de ele descobrir isso, já era tarde, e a solução foi simplesmente abortada.