Desenvolva e mantenha aplicações multi-banco com JPA

Você já precisou desenvolver ou manter uma aplicação com JPA que deve rodar com múltiplos bancos de dados? Mesmo a JPA ou Hibernate simplificando os detalhes de persistência, nós ainda precisamos tomar alguns cuidados importantes para que nossa aplicação seja de fato portável entre bancos, para que ela seja multi-banco.

O blog dos desenvolvedores da TriadWorks acaba de publicar um post onde é enumerado 6 dicas importantes para manter a portabilidade entre bancos da sua aplicação ao trabalhar com JPA. Juntamente com as dicas também é mencionado algumas boas práticas que podemos usar durante o desenvolvimento.

Essas e outras dicas você terá oportunidade de coloca-las em prática durante o curso de Persistência com JPA 2 e Hibernate.

Confira também outros cursos acessando: cursos.triadworks.com.br e mais posts interessantes sobre o dia a dia acessando: blog.triadworks.com.br e bons estudos.

Lançamento dos Cursos de Java da TriadWorks

Lançamento dos Cursos

Demorou, mas a hora chegou! É com muito prazer que anuncio o lançamento dos cursos de Java da TriadWorks. Todos os cursos serão presenciais e acontecerão em Fortaleza-Ceará.

Através do nosso site você confere todos os detalhes de cada curso, como conteúdo programático, valores, formas de pagamento e o calendário com as primeiras turmas. Falando em primeiras turmas, todas elas terão um desconto imperdível de lançamento: 20% de desconto!

Neste momento estamos ofertando 4 cursos, com turmas no período da noite e turmas aos sábados. Todos os cursos incluem apostila atualizada, didática exclusiva e instrutores qualificados com anos de experiência no mercado. Os cursos são:

As vagas são limitadas, apenas 12 alunos por turma, por isso garanta já a sua! Faça a matrícula pelo Paypal e pague em até 6x sem juros – não existe desculpa para não se matricular!

Sala

Em cada curso teremos:

1. Material didático exclusivo e de alta qualidade;
2. Máximo 12 alunos por turma;
3. Um notebook por aluno;
4. Coffe-break em todas as aulas;
5. Blusa exclusiva do curso;
6. Certificado;

IMG_20140115_172933

Dúvidas, reservas ou informações dos cursos para você ou para sua empresa, entre em contato conosco através do formulário de contato no site ou envie um email diretamente para cursos@triadworks.com.br .

Fique por dentro das próximas turmas, descontos, promoções e novidades através da nossa página no Facebook ou Twitter. Acesse agora o site e confira os cursos em http://cursos.triadworks.com.br/ .

HotSpot e JIT Compiler, entendendo como funciona!

Vimos no post anterior como a JVM funciona e como ela detecta e analisa os pontos “quentes” da aplicação. Vimos que os mecanismos que fazem essa análise e melhoria são: HotSpot e JIT(just-in-time compiler) Compiler. Neste post, iremos entender como eles funcionam.

Introdução

Antes de falarmos mais profundamente sobre cada técnica, tentaremos dar um resumo rápido sobre cada uma delas, como segue abaixo:

HotSpot
Quando se executa a aplicação na primeira vez, ela é executada em modo interpretado, ou seja, não é feita nenhuma otimização inicial. Durante a utilização da aplicação, são feitas estatísticas de runtime(durante a execução). Com essas estatísticas é verificado os pontos quentes, os trechos de códigos mais executados do programa. Esses trechos são otimizados, utilizando técnicas bem parecidas com as dos compiladores tradicionais, mas, lembrando que isso tudo é feito em runtime. O HotSpot utiliza a idéia de que apenas 10% do código é executado em 90% do tempo, então a otimização destes pontos isolados permitem um ganho de performance e em até algumas vezes maior do que a compilação tradicional, pois os dados são obtidos diretos da execução real do programa.

JIT Compiler
Compiladores tradicionais(nativos), as otimizações são feitas em tempo de compilação, reordenando instruções, colocando métodos inline(que será explicado mais a frente), otimizando para a máquina que está compilando etc. Isso claro para linguagens como C++ etc.

No Java, isso não funciona: pelo simples fato de que as classes são compiladas em arquivos separados. O compilador JIT irá pegar o bytecode e traduzir tudo de uma vez para a linguagem de máquina antes da execução, esta é a estratégia utilizada pela maioria das VMs. Isso pode ser até um pouco lento inicialmente, mas veremos mais a frente que isso não será um problema.

Aprendendo mais…

O Java por não compilar para código nativo(código da máquina), ou seja, ele não tem um bytecode/executável “preso” a máquina onde ele foi compilado, ele pode e vai usar estratégias focadas no sistema operacional e no hardware usados no momento de execução, podendo até em alguns momentos invocar instruções específicas do processador da máquina.

Em alguns momentos a VM pode perceber que um determinado código já não é mais importante e descartar suas compilações ou até perceber que a otimização que ele fez na primeira vez não foi tão boa assim e pode ser melhorada, dessa forma, ele vai novamente e aplica um novo tipo de otimização e esse ciclo pode ocorrer várias e várias vezes, ou seja, ele pode ficar sempre tentando otimizar seu código ao máximo.

Dessa forma, o seu código irá ficar cada vez mais rápido, devido principalmente a evolução constante da JVM e do JIT. Mesmo programas mais antigos podem ter sua performance melhorada simplesmente atualizando a JVM, sem precisar modificar qualquer linha de código.

Isso já não acontece com um programa nativo(Ex: Word, Excel), onde teríamos que esperar do fabricante uma versão nova recompilada, tanto para o SO atual como para o hardware, processador etc. Quando o fabricante faz uma melhoria no programa, Word por exemplo, você terá que baixar uma atualização dele, um novo “executável”, isso porque os programadores refizeram o código, adicionaram suas melhorias e compilarão novamente, gerando assim o executável.

Essa otimização funciona também para linguagens que rodam em cima da JVM, como o Ruby e várias outras.

Técnica de Inline
Inline de métodos é uma das técnicas utilizada pelo JIT para evitar fazer mais de uma chamada do método.

Veremos um exemplo bem comum:

No método main , existe um loop, onde o mesmo faz referencia ao metodoUM() , ele será executado neste loop 20 vezes. Neste momento o HotSpot irá verificar que esse método main é um código quente, e o JIT irá fazer o inline do método:

Já o métodoUM() , possui também uma chamada para um outro método, o metodoDOIS() …

No final, com o inline “aplicado” a nossa classe ficaria algo semelhante a isso:

O HotSopt também não irá verificar somente a quantidade de vezes que o método é executado, mas também o empilhamento de métodos e chamadas de um método para outro(jumps). O main  chama o metodoUM() , que ele chama o metodoDOIS() , há um empilhamento de métodos. Outro exemplo neste caso:

Exemplo:

Inline:

O HotSpot detecta que esse método está sendo chamado várias vezes, seja por um loop ou por outros métodos, quando percebe que o método está sendo executado várias vezes, então ele aciona o JIT, que “extrai” o conteúdo do método ( outroMetodo ) e adiciona diretamente no método principal( teste ). Essa quantidade de vezes pode e vai variar dependendo do tipo de perfil utilizado pela JVM, claro que o exemplo aqui foi apenas para ilustrar, mas para você ter uma ideia a JVM por padrão aguarda 1.500 invocações ao método até ele ser compilado, já no perfil server, ele irá aguardar em torno de 10.000 invocações.

Tipos de Perfis

Quando desenvolvemos sistemas, sabemos que cada aplicação tem as suas necessidades, sejam de performance, escalabilidade e responsividade. A JVM oferece alguns perfis que adaptam o “motor” JIT e outras características dela para atingir esses objetivos.

Temos então basicamente dois tipos de perfis: Cliente (client) e Servidores (server).

Perfil Cliente

Definindo o perfil “client” algumas configurações e comportamentos serão tomados para com a aplicação. Esse perfil é utilizado para aplicações voltadas para o usuário final, como aplicações desktop, onde a mesma tem que ser inicializada rapidamente, embora depois não precise de tanta performance.

Neste perfil precisamos que a JVM perca menos tempo no startup da aplicação, para que o usuário veja o resultado mais rapidamente, em outras palavras, precisamos que a aplicação Java “abra” mais rápido. Mas isso tem um custo, que é ter um JIT que irá fazer menos otimizações a longo prazo. O foco deste perfil é de consumir menos memória, então, para isso ela deixa de fazer certas otimizações no JIT para evitar o uso excessivo de memória, deixando até de fazer as vezes  o inline de métodos.

Perfil Servidor

Já neste perfil, não temos a preocupação que a aplicação seja iniciada rapidamente, como um sistema que está rodando em um cliente, onde ele pode esperar até que o sistema inicialize, ou um sistema “intranet”, ou até um site ou mesmo um fórum, mas temos uma grande preocupação em performance a longo prazo.

Ele irá demorar mais para startar/inicializar, por outro lado o JIT irá rodar no seu modo mais “completo”, com suas melhores estratégias de otimização para melhorar o desempenho da sua aplicação. Ao contrário do perfil de Cliente, o uso de memória deste tipo de perfil será maior e utilizado com mais frequência,  por outro lado, iremos ganhar uma performance maior e a longo prazo, como o uso de inlines para evitar jumps(chamadas de métodos encadeados, como explicado no inline mais acima) dentre outras técnicas que visam a performance, escalabilidade e estabilidade da aplicação.

Para entender melhor onde cada perfil pode se encaixar, temos uma tabelinha bem simples para nos ajudar a ilustrar melhor:

Arquitetura CPU/RAM OS Perfil
i586 qualquer um MS Windows Client
AMD64 qualquer um qualquer Server
64-bit SPARC qualquer um Solaris Server
32-bit SPARC 2+ cores & > 2GB RAM Solaris Server
32-bit SPARC 1 core or < 2GB RAM Solaris Client
i568 2+ cores & > 2GB RAM Linux ou Solaris Server
i568 1 core or < 2GB RAM Linux ou Solaris Client

Você pode ter mais detalhes sobre os perfís Cliente e Servidor neste link:
http://www.oracle.com./technetwork/java/hotspotfaq-138619.html#compiler_types

Caso o desenvolvedor não saiba como utilizar esses perfis, ou apenas não queira definir um, nas versões mais recentes da HotSpot existe um recurso chamado ergonomics, onde a responsabilidade de escolher o melhor perfil é da própria VM, e não só escolher entre clientserver, mas escolhe o tamanho da heap, algoritmo de coleta de lixo(GC), características baseadas no hardware e processador, o tamanho da memória e etc.

Não temos como entrar a fundo em ergonomics aqui, nosso foco é outro, então deixo com vocês algumas fontes interessantes de pesquisa para tentar entender melhor sobre isso:

Ergonomics no Java 7: http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html
Ergnomics no Java 5: http://docs.oracle.com/javase/1.5.0/docs/guide/vm/gc-ergonomics.html

Se você quer saber mais sobre como otimizar, quais parâmetros utilizar e quais os corretos para cada tipo de máquina, passo alguns links de leitura obrigatório abaixo:

http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
http://docs.oracle.com/javase/7/docs/technotes/guides/vm/server-class.html

Concluindo

Entender melhor como a VM e as técnicas utilizadas funcionam, será bem útil para o seu dia a dia. Ao saber como é feito o inline, como o JIT trabalha, como a HotSpot sabe qual método está sendo executado com frequência, irá lhe ajudar na tomada de decisões, codificação, arquitetura e estrutura da sua aplicação.

A VM do Java é bem poderosa e nos ajuda (e muitas vezes nem percebemos) a melhorar o desempenho do nosso código. Hoje na JVM existem várias outras estratégias de otimização que foram incluídas, como o mecanismo de Garbage Collector por exemplo, que é um dos mais importantes e poderosos mecanismos que a VM possui. Falamos aqui da HotSpot/JIT, que é da VM da SUN/Oracle, mas temos outras VMs de outros fornecedores, como o JRockit da BEA.

Tirar proveito ao máximo da VM é algo que podemos fazer e está em certa parte, diretamente ligada a como você codifica e faz a sua aplicação. Aprendendo de forma correta como utilizar a linguagem a seu favor, você terá esse ganho facilmente. Por isso que no curso de Java e Orientação a Objetos da TriadWorks, sempre estamos passando para os alunos essa premissa que achamos muito importante.

Introdução a JVM – Java Virtual Machine

Introdução

Tão importante quanto aprender a programar em uma nova linguagem ou plataforma, é conhecer e entender um pouco os principais benefícios que ela nos oferece e claro, saber quando e como podemos tirar vantagem do que temos em mãos. No Java, com certeza, a JVM é peça chave e fundamental para a popularidade da linguagem e da plataforma, e é nela onde encontramos todo o poder para termos aplicações performáticas e escaláveis.

Iniciando na Java Virtual Machine.

JVM é uma máquina virtual, como seu próprio nome já diz. E uma das funcionalidades dela é de servir como interpretador para o Java.
Resumindo, o funcionamento é bem simples. Você escreve o código em um arquivo .java, compila, e é gerado um arquivo .class, esse arquivo .class é conhecido como  bytecode. A JVM irá ler/interpretar esse bytecode e executá-lo.

byteCodeJVMLinuxWindows

Dessa forma, um código feito no Linux e compilado no Linux, pode ser executado no Windows, MacOSX ou no seu celular, por exemplo. Essa portabilidade foi o que fez o Java ser tão difundido, tanto que o principal slogan de “venda” da plataforma é: Escreva uma vez, rode em qualquer lugar!

Cada sistema operacional tem a sua JVM rodando e interpretando para a instrução de máquina em que ele se encontra. Mas, será que um interpretador é mais lento do que um código nativo executável?

Porque o Java era considerado lento?

Bem nas primeiras versões do Java, a máquina virtual era apenas um interpretador de bytecode, apenas isso. Ela lia os .class, traduzia cada bytecode para a sua máquina(SO) específica e só, que para época já era um grande avanço.

Então saiu o Java 1.1 e nele foi incluído pela primeira vez, um mecanismo, chamado de JIT Compiler, que foi adquirido da Symantec.

Mais tarde, na versão 1.2 um outro mecanismo foi adicionado, o HotSpot. A partir dai, com a junção dessas duas novas tecnologias adicionadas a JVM e as suas evoluções posteriores até seus dias de hoje, é que faz a JVM ser equiparável e as vezes até mais rápida do que programas escritos nativos em C e C++.

Qual a diferença do binário nativo e bytecode?

Quando compilamos um programa em C, temos uma etapa de compilação estática, assim como no Java também tem. Quando esses arquivos binários são compilados, são feitas algumas otimizações. No C por exemplo, esse binário antes de ser gerado, na compilação receberá algumas otimizações, então só depois disso será gerado um binário executável. No Java ele passa por esse mesmo processo, na compilação, receberá otimizações, mas, ao contrário do C que gera um binário executável na máquina, o Java irá gerar um bytecode, que ainda será interpretado/executado pela VM, e neste momento a VM poderá e irá fazer novas otimizações, otimizando e melhorando ainda mais o programa.

Mas, e se quisermos aumentar a performance desse programa em C?

Teríamos que esperar uma nova versão desse código (compilado para a máquina executada), assim como teríamos que ter a portabilidade para cada SO, processadores Intel ou AMD etc. Ou seja, teríamos que compilar esse código para cada SO que queremos rodar nosso programa, no caso. E ainda mais, o fabricante terá ou não que garantir que essa nova versão compilada do programa, rode em sistemas operacionais “antigos” ou exigir uma portabilidade mínima, como rodar apenas do SO 1.0 superior, algo do tipo.

Como no Java nosso código “se tornou” bytecode, que será interpretado por uma VM, então podemos ter outras otimizações específicas ou não para cada tipo de SO e máquina, isso sem a necessidade de recompilar ou aguardar uma nova versão do programa e sem precisar mexer no código. Isso porque a JVM é quem está executando e interpretando o nosso programa. Como a JVM está sempre sofrendo constantes atualizações e melhorias, basta atualizar a JVM que você terá esses ganhos, sem alterar seu código.

Isso é possível pelo simples fato do Java não fazer a compilação para código nativo , logo ele consegue usar estratégias focadas no SO e no hardware em tempo de execução. E teremos ainda a retrocompatibilidade, que faz ser possível executar um programa em Java feito na versão 1.2 em uma VM da versão 7.0 por exemplo.

Durante essa execução a JVM irá analisar e detectar os pontos mais importantes e mais executados da sua aplicação, que ela chama de “pontos quentes” e então esses métodos ou trechos de códigos são compilados em tempo de execução para instruções nativas e otimizadas. Deixando nosso programa mais rápido, sem nem ao menos precisarmos mexer no código.

“O ganhos reais de performance do Java, devemos à otimização adaptativa, ou seja, é simplesmente a capacidade de se adaptar e fazer otimizações dependendo do uso e das condições do momento (memória, processador etc).”

Quem detecta e analisa esses pontos mais “quentes”, ou seja, esses pontos mais importantes e executados da sua aplicação é o mecanismo chamado de HotSpot, e logo depois ele aciona o outro mecanismo, que é o JIT Compiler.

Não iremos neste post entrar em detalhes sobre eles, o que você precisa entender por enquanto é que:

“O JIT Compiler irá compilar para instrução nativa e otimizada o trecho “quente” e em  VMs mais modernas esse trecho pode até ser recompilado em otimizações mais agressivas, melhorando consideravelmente a performance, claro isso vai variar do fabricante da VM.”

Concluindo

Essa foi uma explicação bem superficial sobre como a JVM funciona e seu objetivo. Lembramos também que a JVM é uma especificação, que possui vários fabricantes, onde temos os mais populares que são da SUN/Oracle e Open JDK.

Podemos observar que ela também pode oferecer muito mais, e com o conhecimento certo e configuração correta, podemos explorar ao máximo toda a potência da VM do Java.

Temas como este fazem parte do cotidiano dos nossos instrutores e claro que não poderiam ficar de fora do curso de  Java e Orientação a Objetos da TriadWorks.

No nosso próximo post, iremos falar mais sobre  essas tecnologias/estratégias adotadas pela JVM que comentamos neste post: JIT Compiler e HotSpot e tentar entender melhor como elas funcionam.