Artigos

Produtividade com Java e Hot Deploying

Olá, pessoal. Feliz ano novo! Passando aqui para deixar umas dicas/previsões de ferramentas para acelerar o desenvolvimento na nossa tão conhecida plataforma Java. Mas aviso que esse artigo ficou bem grande.

Uma coisa que aprendi no desenvolvimento profissional em Java, é que sem dúvidas se trata de uma linguagem poderosa, que precisa de muitas bibliotecas, frameworks, ferramentas e café para poder tentar domá-la. Você pode realmente fazer quase tudo que você pensar em termos de desenvolvimento, testes, implantação, regras de negócios, etc. Uma verdadeira máquina de guerra. Só que apesar dessa máquina de guerra possuir tiros poderosíssimos, demora muito para recarregar o próximo disparo.

Death-Star.jpg

Então, toda vez que você tem que mudar um Bean, cria um Converter, ou qualquer outra coisa no Java EE, precisa-se de uma reinicialização completa do servidor (a parcial, presente em alguns servidores de aplicação, geralmente não funciona direito e a maioria não usa, pois perde-se ainda mais tempo e paciência), apesar da lentidão depender em parte da escolha do servidor que adiciona ainda o seu próprio overhead ao tempo de reinicialização.

Já em Android, felizmente não precisamos de servidores de aplicação, os aplicativos são nativos (nativo no sentido de ser uma única das duas opções disponíveis por padrão para a execução, mas continua tendo um máquina virtual Java), entretanto assim como que o projeto cresce em complexidade fica mais evidente o problema que é fazer a compilação deste tal projeto, precisamos ser responsáveis por gerenciar as nossas libs no projetos, para que uma não sinta falta da funcionalidade de outra, ou pior ainda configurar aquelas que entram em conflito, para que possamos finalmente compilar um apk (o equivalente ao jar com instalador).

Não é fácil, e esse processo todo de gerenciamento de dependências, que tanto o Gradle quanto o Maven fazem, é ótimo, mas não perfeito. No Android Studio, por exemplo, não há ainda a opção de iniciar um projeto sem que o Gradle verifique sempre as versões das bibliotecas, e sempre ao fazer o reload do app, ele vai fazer uma full build novamente, é quase como voltar a usar o Make para compilar um projeto em C/C++ (só que com menos texto de output). E por um tempo foi assim mesmo:

Testar o aplicativo -> Alterar o código -> Reiniciar -> Esperar 2 a 10 min para fazer o build -> Testar o aplicativo.

waiting.jpg

Então como explicado acima, são várias as fontes de morosidade na fases de implementação, testes e implantação usando a plataforma Java. Sendo elas servidor, gerenciadores de dependência e rebuilds. Em relação aos dois primeiros, não há muito o que dizer além desses três conselhos:

  1. Escolha as ferramentas que lhe fornecem um melhor custo-benefício entre suas funcionalidades e o seu overhead.
  2. Essa escolha é relativa a que tipo de situação o seu projeto irá atender, por exemplo, em projetos pequenos como uma aplicação local de gerenciamento de fluxo de caixa de uma farmácia, não há a necessidade de usar um servidor JBoss com Maven, um servidor Tomcat com Ant já dá conta do recado, pois é um projeto tão grande e complexo.
  3. Torça Espere para que saia uma nova versão mais otimizada da ferramenta, que diminua o overhead, de preferência mantendo a mesma estabilidade, e que sua empresa/setor/equipe adote rapidamente a versão mais recente.

Em relação ao build, muitos só que esperam que seja proveniente da Oracle (Java SE/EE/ME) ou do Google (Android) por se resumir basicamente a uma só coisa, o modelo de JVM implementado por cada uma. Porém, não é bem assim, ainda existe um tipo de otimização que se pode realizar aos builds do Java sem ter que esperar novas versões como nos casos acima de servidores e gerenciadores de dependências. E são duas palavras: Hot deploy.

Tá mas o que é Hot deploy? Simples, é criar um meio de apresentar um aplicação a um usuário ou desenvolvedor de forma mais dinâmica e aparentemente quase instantânea, pelo menos que a forma atual de execução. Abaixo detalho algumas das alternativas que encontrei que dizem trazer essa possibilidade ao desenvolvedor.

MODO DEPURAÇÃO DA JVM

Para quem por ventura não saiba, é possível ter um escopo bem estrito de hot deploy, que nos termos usados pela JVM, se chama Hot Code Replace, contudo só tem uma função, alterar o corpo dos métodos de uma classe, qualquer outra coisa que for alterada em modo de depuração, gera o seguinte erro.

HCRF.png

E então será preciso reiniciar novamente, quase tão inútil que muitos não devem nem saber da existência ou a ignoram, os desenvolvedores preferem fazer mudanças mais significativas e realizar um full build da aplicação.

JREBEL PARA JAVA EE & ANDROID

Possivelmente uma das pioneiras nesse trabalho na plataforma Java é a empresa Zero Turn Around, que não só já oferecia a um tempo o seu principal produto, o JRebel para Java EE, um plugin para IDEs Java que realiza um patching na JVM onde opera sobre os bytecodes. Como este ano também lançou seu plugin para Eclipse ADT ou Android Studio.

Das possibilidades disponíveis ao seu modelo de fazer hot deploy estão os seguintes presente na própria página da JRebel.

jrebel.png

A tabela já é autoexplicativa para quem sabe inglês, mas resumidamente, é possível criar/alterar/remover: métodos, campos (estáticos ou não), (super)classes, anotações, enumerações e interfaces.

Agora em relação aos contras. Primeiramente essa ferramenta é paga e bem cara, e segundo é que não foi feita para ambiente de produção, uso somente em desenvolvimento/testes, pois há alteração de bytecodes na realização do build pelo plugin, que corta caminho mantendo uma tabela de mudanças em memória e tal efeito pode não estar disponível em produção por questões de segurança e estabilidade da aplicação.

Algumas notas a acrescentar é que pelo menos para Java EE, existe uma solução no modelo de distribuição, a ZTA oferece uma licença individual, não-comercial e gratuita, sob o título de My JRebel. Um link com um vídeo tutorial do uso do JRebel presente nas referências. Em relação ao plugin para desenvolvimento Android, não há opção gratuita.

Curiosidade: Até Agosto de 2014, existia uma serviço com JRebel, chamado de LiveRebel, que se propunha a proporcionar a possibilidade de hot deploying em ambiente de produção. Porém foi descontinuado.

HOTSWAP AGENT + DYNAMIC CODE EVOLUTION VM (DCEVM)

Alternativamente ao JRebel, existem outras maneiras de fazer o uso em ambiente corporativo sem essa preocupação com assinatura de licenças, uma delas é com o uso da DCEVM, uma versão opensource e modificada da OpenJRE (alternativa de código aberto a Oracle JRE), essa versão modificada da JVM, funciona por meio de um patching realizado por um jar para versões bem específicas da JRE (exemplos, Java 7 update 79 e Java 8 update 51, são as versões mais atuais onde o patch funciona). E um Java Agent modificado, chamado de Hot Swap Agent, que percebe diferenças em classes alteradas e outras classes dependentes, e as recarrega automaticamente em memória com seus bytecodes alterados.

DCEVM.png

O lado negativo é que por se tratar de um projeto opensource e relativamente desconhecido à maior parte da comunidade, ele é desenvolvido num ritmo bem mais lento que o plugin JRebel. E a configuração é manual, desde o patching da JVM, até configuração da IDE (embora a IntelliJ e NetBeans possuirem plugins que ajudam nesta configuração), embora não seja um processo tão difícil.

O esquema de distribuição é feito dos jars Hot Swap Agent (Java Agent alternativo) e do patch para a JVM, sendo que há dois tipos de patching, o full, com basicamente os mesmos recursos do JRebel e o light, um pouco mais limitado (uma comparação completa com o full patch não foi encontrada, só é dito que não há suporte a remoção de superclasses), porém mais atualizado.

Curiosidade: Existe uma JEP (Proposta de melhoria na JDK) de número 159, que solicita a melhoria das capacidades de lidar com Hot Code Replacement, e utilizando a DCEVM como modelo/protótipo. Mas está com status de baixa prioridade, e não consta ainda nos planos de melhorias para o Java 9.

SPRINGLOADED / PLAY FRAMEWORK

Aqui duas alternativas pertinentes ou derivadas de um framework Java. Primeiramente, o Spring-loaded, este funciona de modo parecido ao Hotswap Agent, é outro agente de execução alternativo para a JVM, mas prescinde da utilização de uma versão modificação da JVM, por outro lado deve ser configurado utilizando o Maven. De acordo com a sua página no GitHub, funciona com qualquer versão da JVM, suportando o desenvolvimento inclusive o desenvolvimento com outras linguagens compiladas em bytecodes além do Java. Sendo utilizado para fornecer a capacidade de hotswapping para o Grails Framework e o próprio Spring Framework.

Segundo, uma menção ao Play Framework que também alega ter a capacidade de hot deploy, com a função extra de watching que realiza a recompilação automática das classes e resources presentes no projeto, tanto em modo de desenvolvimento/testes como em modo de produção. O que sem dúvida é um tremendo diferencial, pois a maioria das opções aqui listadas são recomendadas somente em modo de desenvolvimento/testes.

ANDROID STUDIO 2.0

Há uma diferença crucial em relação aos itens anteriores, porque no caso do desenvolvimento para Android é utilizado a IDE fornecida pelo Google em parceria com a JetBrains e a Gradle.org, então a realização de hot deploy vai ser resultado de uma melhoria em várias frentes. Uma delas vai ser feita por melhorias no Gradle, que além de uma ferramenta para o gerenciamento de dependências, é também uma ferramenta de automação de builds. Um dos maior gargalo enfrentado pelo desenvolvedor a cada nova re-execução não se encontra nesta ferramenta de build que demora a condensar o código do projeto com as suas dependências externas em um arquivo apk a ser instalado e executado no dispositivo/emulador, portanto cada (re)execução é tem um limite inferior de lentidão definido pelo desempenho do Gradle em realizar sua compilações. Apesar de algumas otimizações progressivas (no momento em que foi escrito este artigo, estará sendo considerada a última versão do Gradle presente no Android Studio 1.5) para build incremental e paralelo, de modo geral o processo sempre foi bem difícil e demorado.

processo.jpg

Então havia muito o que melhorar para novas atualizações, afinal o Gradle recentemente ainda estava em suas versões 1.x. Agora voltando o foco a IDE, essa versão, no momento está em estágio de prévia, mas futuramente ao período do lançamento de sua versão estável, irá contar com uma configuração de hot deploy, sob a alcunha de Instant Run, e a execução instantânea será feita através de um clique no botão de mesmo nome na barra de ferramentas do Android Studio, a cada alteração realizada.

E como dito anteriormente, o suporte a versões a partir do Gradle 2.0.0, promete ser um dos grandes responsáveis pelo maior dinamismo na execução de um aplicativo, pois enfim a ferramenta vai passar aplicar um build diferencial, quando possível, em vez de sempre fazer um full build ou build incremental (alteração de arquivos extras, à parte do código, como XMLs, SVGs, PNGs, Strings, etc). As alterações de código que dizem que serão passíveis de uso com o Instant Run, são seguintes:

InstantRun.png

Pelo visto acima a execução manterá o estado da aplicação em casos de mudanças em corpos de métodos e adição/remoção de classes, no entanto será preciso entrar novamente na tela (Activity) onde ocorreu a mudança no caso de alterações nas strings. No caso de mudanças imediatamente visíveis, o esquema é bem parecido com o Hot Code Replace da Oracle JVM em modo de depuração, tendo apenas como funcionalidades adicionais a possibilidade de adição e remoção de classes, assim como alterações na Strings (supondo uso das strings em arquivo XML e não de suas variantes hardcoded).

E como último ponto nesse item, outras melhorias significativas em relação ao desempenho serão de atualizações para acompanhar o lançamento do novo emulador para Android SDK, que promete que será mais rápido na instalação e execução dos apks que dispositivos reais rodando o sistema.

CONCLUSÕES

Particularmente eu testei somente o JRebel Java EE/Android, e posso afirmar que são ferramentas de grande qualidade e muito úteis, mas dentre todas a opções acima é o único item pago e/ou que tem restrições de uso, para pessoas que estão aprendendo a plataforma Java EE/SE ou querem testar para confirmar a viabilidade para si ou sua equipe ou sua empresa, é uma excelente alternativa. Em termo de suporte e possibilidade de mudanças no projeto passíveis de hot deploying também é a melhor ferramenta desta lista.

Em relação ao DCEVM, é surpreendentemente de bom uso e ainda relativamente fácil de configurar, mas tendo em mente que devido aos patches só estarem disponíveis em algumas versões de updates bem específicos da plataforma JRE pode ser que não cubra a versão em uso no seu trabalho, e quanto ao suporte para o Java 8 ainda é com patches light, logo com menos recursos, pode não ter todo o apelo JRebel, nem o mesmo nível de atividade, mas vale a pena conferir, pois funciona sob licença opensource, ou seja, caso tenha experiência suficiente para fazer hacking na JVM e queira, pode submeter melhorias no GitHub do projeto. Sem falar, que possivelmente, infelizmente não em curto prazo, fazer parte das melhorias presentes em uma futura versão da própria Oracle JDK, tudo depende do sucesso do projeto e adesão pela comunidade, como foi com outros frameworks Java no passado, a exemplo do Hibernate que inspira a homologação da especificação JPA.

Sobre o Spring-loaded e o Play Framework, um dia espero testá-los mesmo que somente em aplicativos básicos, com o Spring-loaded é preciso se preocupar com configuração do Maven, mas também acho bom desenvolvê-los em seus fluxos de trabalho originais, onde a configuração e o suporte devem ser melhores, isto é, Spring-loaded com o Spring Framework ou Grails e o Play Framework já sendo monolítico no seu fluxo de programação reativa (que por sinal, vem se tornando uma nova tendência nesses últimos anos, junto aos conceitos de programação funcional do Java 8/Scala).

Sobre as novidades para o Android Studio 2.0, que prometem simplificar as coisas, resta esperar pois o status atual da integração deste conjunto de ferramentas é muito imaturo e provavelmente contendo ainda vários bugs. Ainda assim temos um estimativa e uma espera menor do que pela incorporação dos recursos de hotswap do DCEVM numa versão oficial da JDK.

Por fim, e fora do escopo deste artigo. Existem/Existirão outras formas de soluções a médio/longo prazo para conseguir mais dinamismo na execução de projeto Java em Geral. Afinal surgem outras ferramentas de automação de build alternativas para Oracle Java/Android como o Buck e Bazel, do Facebook e da Google, respectivamente, que prometem acelerar o builds, mas ainda são bem incipientes (nenhum dos dois tem suporte a Windows, no momento). Em relação aos planos da Google, além do lançamento AS 2.0, pretende utilizar o Bazel em futuras versões do Android Studio esse ano e anunciou essa semana que vai passar a usar OpenJDK em vez da JDK proprietária (então ao menos, há uma mínima possibilidade de que ela venha a tomar conhecimento do projeto DCEVM e resolva contribuir/usufruir do mesmo). Quanto a Oracle, algo que tem grandes chances de estar presente no lançamento do Java 9 é o resultado do projeto Jigsaw, que permite trazer modularidade nativa a JVM, possibilitando a componentização de projetos, podendo por exemplo, realizar a manutenção, adição e remoção de funcionalidades em tempo de execução e em ambiente de produção, semelhante a proposta do OSGi e microservices.

REFERÊNCIAS

JRebel

Hotswap Agent + DCEVM

Spring-loaded / Play Framework

Android Studio 2.0

  1. http://www.i-programmer.info/news/193-android/9210-android-studio-2.html
  2. http://android-developers.blogspot.com.es/2015/11/android-studio-20-preview.html
  3. https://sites.google.com/a/android.com/tools/tech-docs/instant-run

Buck / Bazel / Project Jigsaw

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *