You are currently browsing the category archive for the ‘Java’ category.
Palavras-chave: Java, hash, MD5, SHA-1, SHA-256, MessageDigest
A maneira mais comum de se gerar um código hash em Java é utilizando a classe java.security.MessageDigest. O método a seguir gera o hash MD5 de uma string:
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(frase.getBytes());
byte[] hashMd5 = md.digest();
O hash é retornado como um array de bytes, que pode ser impresso utilizando o método citado em um post anterior:
private static String stringHexa(byte[] bytes) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
int parteAlta = ((bytes[i] >> 4) & 0xf) << 4;
int parteBaixa = bytes[i] & 0xf;
if (parteAlta == 0) s.append('0');
s.append(Integer.toHexString(parteAlta | parteBaixa));
}
return s.toString();
}
Além do MD5, podemos também usar outros algoritmos de hash normalmente presentes nas distribuições da JVM. O exemplo a seguir gera os códigos MD5, SHA-1 e SHA-256 da mesma mensagem:
public static byte[] gerarHash(String frase, String algoritmo) {
try {
MessageDigest md = MessageDigest.getInstance(algoritmo);
md.update(frase.getBytes());
return md.digest();
} catch (NoSuchAlgorithmException e) {
return null;
}
}
public static void main(String[] args) {
String frase = "Quero gerar códigos hash desta mensagem.";
System.out.println(stringHexa(gerarHash(frase, "MD5")));
System.out.println(stringHexa(gerarHash(frase, "SHA-1")));
System.out.println(stringHexa(gerarHash(frase, "SHA-256")));
}
A saída deste programa será:
51408e7592917e916b55f8021a0f7ad3 5907736c4de6fdd70fcdc7517c3aebd257a1addc ed40c896d779f946956483d45e9efe08aac6373935d354c2be2136bf05bca42c
Palavras-chave: Java, Java 5, coleções, iteração, genéricos
A linguagem Java já tem mais de uma década de idade e naturalmente evoluiu neste período. Verifique se o jeito que você usa coleções está atualizado.
Antes do Java 1.2, a classe para representar arrays dinâmicos era a java.util.Vector:
Vector ps = new Vector();
ps.addElement(new Pessoa("Maria 1.1"));
for (Enumeration e = ps.elements(); e.hasMoreElements();)
System.out.println(((Pessoa) e.nextElement()).getNome());
O Java 1.2 trouxe as classes ArrayList, LinkedList, HashMap, HashSet, que, em conjunto com outras, formaram o Collections Framework, uma biblioteca padronizada e bastante completa para lidar com coleções de valores. Algumas das novidades:
-
Os nomes de métodos ficaram mais curtos.
-
A hierarquia de classes e interfaces está mais bem formada e útil. Por exemplo, LinkedList e ArrayList podem ser generalizadas como List.
-
Foram feitas algumas otimizações de performance. Por exemplo, ArrayList não tem todos os métodos synchronized, como Vector.
Exemplificando:
List ps = new ArrayList();
ps.add(new Pessoa("Maria 1.2"));
for (Iterator i = ps.iterator(); i.hasNext();)
System.out.println(((Pessoa) i.next()).getNome());
No Java 1.5 (ou Java 5), além das evoluções normais da API, houve também algumas mudanças na própria linguagem:
List<Pessoa> ps = new ArrayList<Pessoa>();
ps.add(new Pessoa("Maria 1.5"));
for (Pessoa p : ps)
System.out.println(p.getNome());
Como se vê, as coleções podem agora usar tipos genéricos e há uma nova estrutura de for, chamada for-each.
Portanto, se de vez em quando você ainda se encontra usando Vector, procure atualizar-se para poder evoluir junto com a linguagem daqui para frente.
Palavras-chave: java, permgen, falta de memória, geração permanente
A máquina virtual Java tem uma área de memória limitada chamada Geração Permanente (Perm Generation), onde são armazenados objetos cuja desalocação é rara (ex.: código de classes, objetos de reflexão, pool de strings etc). Dado que esta área de memória é limitada, seu uso intenso pode gerar erros com a seguinte mensagem:
java.lang.OutOfMemoryError: PermGen space
Como a mensagem diz, isto acontece porque não há mais espaço na memória reservada para a Geração Permanente. Para que este problema não aconteça mais, use a opção -XX:MaxPermSize na inicialização da JVM. Isso aumentará o tamanho máximo da memória de Geração Permanente, como no exemplo a seguir:
java -XX:MaxPermSize=128m pacote.MinhaClasse
Neste caso, configuramos o tamanho máximo da memória de geração permanente para 128 megabytes, sendo que o tamanho padrão é 64 megabytes.
Uma demonstração pode ser feita com o código a seguir:
public class TestePerm {
public static void main(String[] args) {
int numeroDeAlocacoes = 0;
try {
System.out.println("Alocando...");
ArrayList list = new ArrayList();
String grandeString = new
BigDecimal(1000).pow(1000).toString();
for (int i = 0; i < 1000000; i++)
list.add((grandeString + numeroDeAlocacoes++).intern());
System.out.println("Fim.");
} catch (OutOfMemoryError e) {
System.out.println(e);
System.out.println("Alocacoes antes do erro: " + numeroDeAlocacoes);
}
}
}
Este programa usa o método intern() da classe String para alocar strings no pool da JVM e fazer estourar a memória de geração permanente.
A seguir, vemos dois exemplos de execuções do programa TestePerm:
$ java codare.TestePerm Alocando... java.lang.OutOfMemoryError: PermGen space Alocacoes antes do erro: 11087 $ java -XX:MaxPermSize=128m codare.TestePerm Alocando... java.lang.OutOfMemoryError: PermGen space Alocacoes antes do erro: 22183
Na primeira execução, com o MaxPermSize configurado para 64 megabytes (tamanho padrão), conseguimos colocar apenas 11087 strings no pool antes de acabar a memória permanente. No segundo caso, com 128 megabytes de MaxPermSize, conseguimos fazer 22183 alocações.
A área de geração permanente é usada intensivamente em servidores de aplicação, pois estes executam milhares de classes e ficam meses no ar. Portanto, em um ambiente de produção, nunca se esqueça de configurar um tamanho máximo adequado para a memória permanente da JVM.
Palavras-chave: java, byte, conversão, hexadecimal
Em Java, as conversões e promoções numéricas às vezes fazem tarefas simples parecerem complicadas. A seguir, um método rápido para imprimir um array de bytes.
public class ImpressaoBytes {
public static void main(String[] args) {
System.out.println(paraStringHexa(
new byte[] { 0x0F, 0x7f, 0x3d, 0x00, -0x23 }));
}
private static String paraStringHexa(byte[] bytes) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
int parteAlta = ((bytes[i] >> 4) & 0xf) << 4;
int parteBaixa = bytes[i] & 0xf;
if (parteAlta == 0) s.append('0');
s.append(Integer.toHexString(parteAlta | parteBaixa));
}
return s.toString();
}
}
Para cada byte, o truque é simples: deslocamos para a direita, desprezamos o que não seja a quadra menos significativa (& 0xf) e deslocamos de volta para a esquerda; para a parte baixa, é só desprezar o que não for a quadra menos significativa.
Então basta usar o conversor de int para string hexa. A saída do programa será:
0f7f3d00dd
Uma provável tentativa seria substituir o laço por:
for (int i = 0; i < bytes.length; i++) {
s.append(Integer.toHexString(bytes[i]));
}
Mas isso falharia ao se tentar imprimir bytes “negativos”, como o último de nosso array de exemplo. A saída incorreta seria:
f7f3d0ffffffdd







Comentários Recentes