Embora o titulo desse post possa parecer estranho, ele refere-se a um OutOfMemoryError que pode ocorrer em uma situacao (bem especifica e verdade), mas que aparentemente nao deveria. Sem mais delongas, segue o codigo:public class Foo { public static void exec(int size) { { byte[] someData = new byte[size]; process(someData); } //final do bloco byte[] someData = new byte[size]; process(someData); System.out.println("ok"); } private static void process(byte[] data) { } public static void main(String[] args) { exec((int) (0.7 * Runtime.getRuntime().maxMemory())); } } O codigo acima lanca uma OutOfMemoryError: java heap space, muito embora nao devesse, ja que o objeto 'someData' sai de escopo apos a linha 7, quando o bloco termina. A primeira impressao que pode ficar e, como as duas alocacoes estao proximas, nao da tempo para o GC limpar a memoria. Tentaremos, entao, chamar explicitamente o GC para ser executado no meio tempo:public class Foo {public static void exec(int size) { { byte[] someData = new byte[size]; process(someData); } //final do bloco System.gc(); byte[] someData = new byte[size]; process(someData); System.out.println("ok");}private static void process(byte[] data) {}public static void main(String[] args) { exec((int) (0.7 * Runtime.getRuntime().maxMemory()));}}Mesmo desse jeito, o codigo continua com o OutOfMemoryError. Algumas pessoas familiarizadas com o funcionamento do GC podem afirmar que chamar System.gc() nao necessariamente implica no GC ser executado de verdade. Mas o codigo abaixo mostra(?) que, se formos insistentes, a memoria e coletada apropriadamente:public class Foo { public static void exec(int size) { { byte[] someData = new byte[size]; process(someData); } //final do bloco for(int i = 0; i < 10; i++) System.gc(); byte[] someData = new byte[size]; process(someData); System.out.println("ok"); } private static void process(byte[] data) { } public static void main(String[] args) { exec((int) (0.7 * Runtime.getRuntime().maxMemory())); } } E tambem podemos ver que gerenciando "manualmente" a memoria (ou seja, anulando a variavel someData ao final do bloco), o codigo funciona normalmente:public class Foo {public static void exec(int size) { { byte[] someData = new byte[size]; process(someData); someData = null; } //final do bloco byte[] someData = new byte[size]; process(someData); System.out.println("ok");}private static void process(byte[] data) {}public static void main(String[] args) { exec((int) (0.7 * Runtime.getRuntime().maxMemory()));}}Por que sera que se insistirmos, o problema some? Mais do que isso, ha um problema com o gerenciamento de memoria da VM? Devemos esquecer que o GC existe e gerenciar a coleta de objetos manualmente, anulando todas as variaveis quando elas deixam de ser usadas? Hoje foi o ultimo dia do JavaOne 2011. O dia abriu com um keynote da IBM antes da Community Keynote. O representante da Oracle (Jason McGee) falou bastante sobre o cloud e como a IBM (e o comite do JEE) pretende facilitar a vida dos desenvolvedores Java. McGee tambem citou um GC diferente chamado Balance Collector que me pareceu interessante e estara disponivel no JDK7 do J9 (a JDK da IBM) para ser usado em sistemas com heaps muito grandes. McGee tambem reenforcou o comprometimento da IBM com Java ha muito tempo (e mais recentemente, quando eles entraram no OpenJDK). O KeyNote da IBM se seguiu com 1 minuto de silencio pela morte de Steve Jobs