AutoBox/UnBox é a conversão de forma automática entre objetos e tipos primitivos, dicas:

  • Use somente quando houver “descasamento” entre tipos primitivos e objetos empacotadores
  • Não abuse: um Integer não substitui um int (a performance é pior)
  • Cuidado, unboxing com objetos null lança exceção

Probolema:

  • Generics não trabalha com tipos primitivos

Após executar o seguinte teste de performance, constatou-se uma diferênça em média de 25% com uso do autobox. O algoritimo de teste baseou-se em comparar as duas execuções:

  1. faça 1000 vezes
    • varra um ArrayList<Integer>, capturando o valor sem fazer autobox
  2. faça 1000 vezes
    • varra um ArrayList<Integer> usando enhanced-loop fazendo automaticamente unbox para int, capturando o valor e fazendo autbox novamente para um objeto Integer.

Resultado da execução:

___________________________________

autoBoxUnBox()…java.lang.NullPointerException
Sem autoboxing = 6531ms
Com autobox/unbox= 8734ms
Diferença de 26%

___________________________________

Conclusão:

Se sua aplicação é “Performance Driven”, estruturas como o IntHashMap visto no blog anterior entre outras coleções da API que não trabalhem com Generics podem ser a melhor saída para escovar milisegundos de processamento.

Abaixo segue a classe usada no teste:

Leia o resto deste post »

O java.util.HashMap como o próprio nome diz utiliza-se do hash code do objeto “chave” para mapear as entradas do mapa. Funciona basicamente assim:

HashMap map = new HashMap();
map.put("matricula.12345", "Fabricio");

A essência do funcionamento do método put() é :

public void put(Object key, Object value){
 int hash = geraHashCode(key);
 int  posicao = geraPosicaoNaTabela(hash);
 adicionaNaTabelaDeEntradas(posicao, value);
}

Quando porém estamos trabalhando com um mapa onde as chaves já são inteiros muitas operações do mapa podem ser simplificadas, solução: IntHashMap.
Algumas coporações como a Oracle, Apache, etc… possuem em suas “foundation classes” alguma implementações que trababalhem desta forma para obterem melhor performance. Afim de comparar o desempenho com HashMap executei dois teste simples

  1. Povoando o mapa com 1000000 chaves sequenciais (Puts)
  2. Recuperando todos os objetos do mapa (Gets), utilizou-se string como objeto para evitar autobox/unbox.

O resultado foram ganhos em média de 70% para os puts, e 30% para os gets efetuados no mapa. Veja o resultado de uma excução:

Main.testSunMap()…
Main.testIntMap()…

‘Puts’ execution time (milliseconds):
sunMap: 3328 intMap: 922, Percentage of gain: 73%

‘Gets’ execution time (milliseconds):
sunMap: 234 intMap: 140, Percentage of gain: 41%

Conclusão
Se suas chaves são inteiros use IntHashMap. Os resultados foram obtidos usando java 5, o mesmo exemplo foi executado com 1.4 e obteve em média os mesmos valores, no entanto se em sua aplicação você não tomar os devidos cuidados no uso do autoboxing/unboxing de valores primitivos para objetos, a diferença de ganho vai ser ainda em muito melhor para o IntHashMap devido a perda de performance executando o boxing.

Leia o resto deste post »

Você já se perguntou como algumas IDE’s configuram o classpath da sua aplicação dinamicamente em tempo de execução?

Aqui vai uma solução técnica alternativa (that means GDD – Gambiarra Driven Development :P ).

A classe java.net.URLClassLoader é o classloader default do sistema para carregar o jars do classpath quando o aplicativo java é iniciado.
Uma maneira de adicionar jars extras seria invocando no classloder o método addURL(URL url), o que faz o jar localizado por está URL ser carregado na JVM em execuçao. O problema é que este método é protegido (protected) e portanto, a menos que você extenda o URLClassLoader, sobreescreva o método mudando a visibilidade para público e configure seu classloder como default do sistema você não poderá invocá-lo na instância do classloader.
Mas como nem tudo é impossível na computação, você pode contornar o problema usando reflexão e acessando o método protegido. Para isso basta recuperar o método “addURL” declarado e invocar setAccessible(true).

A classe abaixo mostra como você mata os dois coelhos com uma única cajadada:


public class ClassPathHacker {

private static final Class[] parameters = new Class[]{URL.class};

public static void addFile(String s) throws IOException {
 File f = new File(s);
 addFile(f);
}//end method

public static void addFile(File f) throws IOException {
 addURL(f.toURL());
}//end method

public static void addURL(URL u) throws IOException {

	URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
 Class sysclass = URLClassLoader.class;

	try {
 	Method method = sysclass.getDeclaredMethod("addURL",parameters);
 	method.setAccessible(true);
 	method.invoke(sysloader,new Object[]{ u });
 } catch (Throwable t) {
 	t.printStackTrace();
 	throw new IOException("Error, could not add URL to system classloader");
 }//end try catch

}//end method

}//end class

Baseado no Fórum:

http://forum.java.sun.com/thread.jsp?forum=32&thread=300557&tstart=0&trange=15