O legal por aqui é que sempre quando sai prrd*, geralmente sai tb algo de bom do meio. O ideal é pular a parte da prrd* e ir direto ao debate quente mas educado.
Faça um programa que não libere nenhum objeto para o GC, rode ele com verbose:gc e veja se o GC vai acordar. Aqui no meu linux box ficou rodando por uma hora sem printar nada. Depois fui dormir…
Se vc baixar o openjdk e dar uma olhada no código do SelectorImpl e do EPollSelectorImpl vai ver que o primeiro leak iterator a cada interação e o segundo está explicitamente chamando new Integer(nextFD) também dentro do loop!!!
Uma observação que fiz aqui há alguns posts atrás é que como o loop do selector vai rodar algumas milhares de vezes, pode não demorar muito para termos bilhões de inteiros no cache, no caso de vc mudar para autoboxing e usar o pool de wrappers. Interessante essa sua observação de que esse pool é limitado. Um pool de 4 bilhões de inteiros provavelmente não seria legal…
E a questão de primitivos eu concordo com vc e com o Doug. Já que Java tem primitivos então ela poderia vir de fábrica com collections para primitivos. Aqui nós implementamos nossas próprias collections de primitivos. Parece que Jakarta Commons Collections tb tem algumas. Outra opção seria controlar vc mesmo o pool de Integers, mas para isso vc precisa de um integer mutátvel. Um int[] com tamanho 1 é basicamente isso.
Como falei antes tb, num ambiente single-threaded (NIO), essas estruturas de dados podem ser otimizadas ao extremo e sem qualquer sincronização. Um pool de objeto acaba virando uma simples LinkedList.