Ontem eu estava muito contente porque depois de tres fim de semanas de trabalho arduo consegui enfim terminar todas as melhorias que eu tinha planejado para o meu prototipo da minha tese que estou fazendo em java.
Fiz varios testes, dados diferentes, tudo correndo bem, dai tive a brilhante ideia de ter no log as informacoes da thread, fiz um toString bem legal:
public String toString() {
if (thisToString == null) {
StringBuilder sb = new StringBuilder(this.hashCode());
sb.append("-");
sb.append(databank.toString());
thisToString = sb.toString();
}
return thisToString;
}
Testei umas vezes, achei que estava um pouco mais lento que o normal, mas nao dei bola, gerei o jar, e mandei para o servidor que uso de teste. Continuei achando que estava um mais lento que o normal, culpei o servidor e fui dormir tranquilo.
Hoje durante o dia fui algumas vezes ver como estava rodando e percebia que estava bem mais lento que o comum. Por exemplo, o processo todo ocorria em 90% dos casos em menos de 1 segundo e em mais de 50% em menos de 600milli segundos. Hoje dificilmente executava em menos de 3 segundos. Puta que pariu, tem algo de estranho ai.
Chegando hoje do google, sentei no computador e comecei a depurar, coloquei a culpa no esquema de fila de execucao que usa o ExecutorService que comecei a usar ontem, gastei uma hora nisso e nada… entao coloquei culpa no windows: “Essa merda fica fazendo IO a toa, o scheduler esta louco” e outras disculpas que se inventa.
Cheguei no linux, eclipse, netbeans, console… algo de estranho aconteceu, ao inves ficar lento, simplesmete dava o erro de falta de memoria. Puta que pariu de novo, os parametros estao errados… arrumei, ou nao, porque estavam certos, e voltei a executar, o erro nao passava.
Dai tive a brilhante ideia de prestar atencao na stack”trance” do OOM. StringBuffer? OutOfMemory ali? Este troco esta bugado, so pode… Atualizei o jdk, jvm, tudo… e continuava.
Entao tive a segunda ideia genial, depurar o codigo e ver porque diabos da OOM ali.
Voltando ao codigo que coloquei antes, a linha que dava erro:
StringBuilder sb = new StringBuilder(this.hashCode());
Puta que pariu de novo! Ele aloca um stringbuffer do tamanho do hash, por algum motivo desconhecido o valor do hash no jvm linux eh gigantesco, “1024180126” enquanto no windows eh menor, da OOM no Linux.
Subtitui a linha defeituosa por algo correto:
StringBuilder sb = new StringBuilder(Integer.toString(this.hashCode()));
e bingo, o que antes demorava 3 segundos, voltou aos 100milli!
Conclusao, ao inves de culpar codigos, SOs e etc… gaste 5 minutos e depure seu programa :-)