Categorias
Eclipse Java

Alternativa gratuita ao JRebel

É na hora do stop / start dos servidores Java que bate aquela inveja do PHP, que consegue fazer um refresh geral apenas com um F5 no browser.

A empresa que resolveu esse problema (ZeroTurnaround) está ganhando uma boa grana com isso, vendendo licenças a um dólar por dia com o software JRebel

jrebel_logo-RGB

Entretanto, um excelente projeto semelhante não tem ganhado o foco que merece, talvez pela falta de usuários ou de documentação.

Conheça a alternativa gratuita e livre: Dynamic Code Evolution Virtual Machine ou simplesmente DCE-VM, criada pelo desenvolvedor Thomas Würthinger que colocou sua tese em prática.

Ao contrário do JRebel, que encapsula a JVM para fazer o hotswap das classes, o DCE-VM altera o seu JRE, substituindo o hotswap limitado da JVM tradicional.

Atualmente o projeto está no github, e o link para download as versões recentes é esse: https://dcevm.github.io/

Se você usa o IntelliJ, tem um plugin pronto pra ele.

Se você usa Eclipse ou outro editor, vou explicar aqui como é simples o seu uso.

Os passos são esses para usar a sua aplicação com o Apache Tomcat 7 :

  1. baixar uma JDK compatível 1.7 ou 1.8 se necessário;
  2. instalar o DCE-VM na JDK;
  3. configurar o seu ambiente para usar essa JDK;
  4. adicionar CMSClassUnloadingEnabled nos parâmetros da JVM;
  5. conectar em modo Debug à JVM do Apache Tomcat 7;
  6. codificar, gravar e testar no browser \o/

Eu fiz o teste com a JDK 7 update 51 – 64 bits instalada em um diretório alternativo: /home/fb/jdk/jdk1.7.0_51 baixando o
instalador para essa mesma versão.

Depois iniciei o instalador:

$ java -jar installer-full-jdk7u51.3.jar

O instalador identifica as instalações de JDK existentes:

dce-vm1

Clicando na opção “Add installation directory…“, adiciono o diretório /home/fb/jdk/jdk1.7.0_51 :

dce-vm2

Depois escolhendo a opção “Replace by DCEVM” o instalador faz a troca:

dce-vm3

Ao exibir a versão do Java verificamos que foi instalado com sucesso:

fb@cascao ~ > /home/fb/jdk/jdk1.7.0_51/bin/java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Dynamic Code Evolution 64-Bit Server VM (build 24.51-b03-dcevmfull-3, mixed mode)

Nos meus projetos eu uso o plugin do Maven para subir o Tomcat 7 localmente:

<plugin>
 <groupId>org.apache.tomcat.maven</groupId>
 <artifactId>tomcat7-maven-plugin</artifactId>
 <version>2.2</version>
 <configuration>
  <port>8080</port>
  <path>/</path>
 </configuration>
</plugin>

Usei um projeto bem simples com Spring, com um controller assim:

@Controller
public class TesteController {

    @RequestMapping(value = "/teste",method = RequestMethod.GET)
    protected void teste(ModelMap model) {

        model.put("valor","Funciona ?");

    }
}

 

Que chama uma página JSP extremamente simples:

<html>
<h1>${valor}</h1>
</html>

Subi o servidor com o script abaixo, note os parâmetros da JVM de debug junto com o CMSClassUnloadingEnabled:

export JAVA_HOME=/home/fb/jdk/1.7
export PATH=$JAVA_HOME/bin:$PATH
export MAVEN_OPTS=" -Xmx512m -XX:MaxHeapSize=512m -XX:MaxPermSize=512M -XX:+CMSClassUnloadingEnabled -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=n"
 
mvn clean install tomcat7:run

Acessando a página de teste, temos:

dce-vm4

Agora, pelo Eclipse conectamos ao servidor em modo debug:

dce-vm5

E vamos fazer uma alteração no sistema, criando uma nova classe:

public class Teste {

    public String nome() {
        return "Siiiim ! http://www.boaglio.com";
    }
}

E alterar a classe existente para chamar a classe nova:

@Controller
public class TesteController {


    @RequestMapping(value = "/teste",method = RequestMethod.GET)
    protected void teste(ModelMap model) {

        model.put("valor","Funciona ? "+ new Teste().nome());

    }

}

E fazendo o reload, percebemos a página atualizada:

dce-vm6

Uau! Atualizou sem stop / start!

happy-cuteness-overload-l

Uma lágrima caiu do seu olho e finalmente você pode comparar PHP ao Java… =)

Mas calma lá, nem tudo são flores… hoje em dia sempre usamos frameworks, e as vezes nem esse hotdeploy adianta, pois, por exemplo, o Spring MVC possui um contexto que é registrado no início da aplicação, se você, pode exemplo, adicionar uma classe nova e usar @RequestMapping(value = “/outro-teste”) não vai funcionar, pois a classe nova está lá, mas o contexto do Spring continua o mesmo.

Nesse sentido o JRebel é bem mais maduro, mas com certeza o DCE-VM te salvará alguns minutos ou horas de sua vida, aproveite! . =)

Fernando Boaglio, para a comunidade