Blog sobre desenvolvimento de software (Java, muito Java!), inovação tecnológica e cotidiano do Universo de TI. Acesse notícias, tutoriais, material de cursos e eventos, código, desafios, soluções, opiniões, pensamentos, divagações, balbuciações e abobrinhas diversas. Deixe seu comentário!

terça-feira, 8 de outubro de 2013

Java IDES - One shortcut to rule them all

"Three IDES for the Java-kings under the sky,
Seven were once famous in their halls of stone,
Plenty of others for Mortal Men doomed to die,
One shortcut to the Productivity Lord on his dark throne
In the Land of Java where the Shadows lie.
One shortcut to rule them all, One shortcut to find them,
One setting to bring them all and in the darkness bind them
In the Land of Java where the Shadows lie."
- J. R. R. Tolkien, The Lord of the Rings (slightly hacked)

I've been a polyglot programmer and multi-IDE user for several years... And as any all-arounder, I am not the most productive expert on any of them. IDES are huge beasts! It takes time to learn and to allow all of its functionality to sink in and it takes even more time to learn how to do things efficiently. 

Memorizing highly specific keyboards shortcuts of each IDE is one of the many actives that can become tedious or even completely unachievable if you switch between IDES frequently. Still, all in all I do prefer this road, since every IDE has its unique qualities. I'm a huge believer of the motto "Use the right tool for the job." Quoting the amazing Abraham H. Maslow's Psychology of Science: "I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail." Please avoid temptation!

So let's check out how to cheat and increase productivity by learning "Tool tamer" shortcuts for the most popular IDES in Javaland.


The idea behind this article is that if you can learn how to find desired functionality in the sea of options that one IDE has to offer, then you can teach yourself to be more productive with it. If you can configure all of your IDES to use the same shortcut to access the desired functionality then congratulations, you have just created a shortcut to rule them all.

Eclipse


If you make a living out of Java, chances are that you have spent some time with Eclipse, either because you love it or because that's what everyone else in your company uses! Eclipse is the only IDE that an entire army of (not that enthusiastic) Java Developers have ever learned how to use: it often offers the only best third-party plugins for a certain software stack. Eclipse is the most popular IDE in Javaland. Developed by an impressive foundation - backed by a giant group of technology companies and fueled by a vibrant community - the extremely customizable SWT-based IDE conceived by IBM isn't going away anytime soon.

If you don't know how to do something in Eclipse, just resort to the handy Quick Access functionality (Ctrl+3) and type the desired action (say, "Extract Variable").


If you don't like Ctrl+3 just bind the Quick Access command to some other key combination. In order to do this follow these steps:
  1. Navigate to Windows Preferences
  2. In the right menu open General → Keys
  3. Locate and select Quick Access
  4. Change its binding to the desired key combination
  5. Click on Apply and OK
 


Netbeans


"The only IDE you need" was the Netbeans motto back when Sun shined. It is intriguing to observe how  a lot of my colleagues dismiss this very crafty IDE as "slow"... This might have been true once upon a time when Netbeans hadn't yet reached its fourth release, the VMs were not optimized for Swing Applications, and computers were shipped with way less memory and very poor graphic cards. Nowadays Netbeans is a very responsive IDE with amazing UI Design Tools (JavaFX anyone?), a great out-of the-box experience for Java SE and Java EE, out-of-the-box support for a variety of Java tools and frameworks, plus a surprisingly competent out-of-the-box support for other programming languages (such as PHP, Groovy and C/C++). Netbeans surely lives up to its motto, and does this with a clean, hassle-free philosophy which makes it the perfect IDE to use in classroom.

Much in the same fashion of Eclipse, Netbeans exposes a Quick Find command which can be triggered with Ctrl+l. Although unlike Eclipse, Netbeans tries to find a lot of things by default (Types, Symbols, Help references, Maven artifacts and so on). So if your goal is to find an IDE functionality it is advisable to narrow the search category (accessible with Shift+F10 when the cursor is on the search bar) to Action.


I have never really liked Ctrl+l as a shortcut to Quick Find. So Thanks Sun for shortcut customization. To change your keymap, do the following:
  1. Navigate to Tools Options
  2. Click twice on the Keymap button located at the top Toolbar
  3. Look for "Quick search"
  4. Click in the Shortcut cell (or on the small ellipsis button) to edit
  5. Type your new key combination
  6. Click on OK



IntelliJ IDEA


How does a company make money out of a Java IDE when programmers can just download very good IDES such as Eclipse and Netbeans for free? Easy, you make the best tool on the market! And that's exactly what JetBrains did with IntellliJ IDEA. But don't take my word for it: just read what Martin Fowler has to say about IntelliJ (in its way, Martin Fowler is the IT version of Tom Hanks, we can always borrow its credibility). While there is a free Community Edition (which is good enough to run the amazing Scala Plugin, light years ahead of the competition) the good stuff comes with a price tag.
Is it worth it? Sure! I think that IntelliJ is indeed the Best Java and Polyglot IDE there is. I feel that developing with IntelliJ is a pleasure. Yes, I think that it can read my mind. And yes, I'm sold. But no, I'm not on commission, although if someone at Jetbrains ever reads this article and feel like donating a lifetime IntelliJ license, I'm all for it)!

God is in the detail!  And IntelliJ Find Actions command has a very different (and, in my option, way better) approach for searching actions than Eclipse and Netbeans top right corner search boxes... Ctrl+Shift+a makes IntelliJ pop up a contextual menu right in the middle of your code. Easy, fast and to the point.


If Ctrl+Shift+a stresses your fingers (or your brain), no problem - here is the receipt to change it:
  1. Navigate to File → Settings
  2. At the left menu click on Keymap
  3. Look for "Find action"
  4. Click twice on it to customize the shortcuts
  5. Click on Apply and OK

And that's all: you've learned how to find your actions and teach yourself new shortcuts using three of the most popular Java IDES. Plus you have mastered how to customize key bindings according to your desires. Now come on, don't be a Hobbit (or eight Hobbits, also know as a Hobbyte)! Use the precious shortcut... Rule them all!

terça-feira, 1 de outubro de 2013

POSCOMP 2013

Quem leu meu artigo "POSCOMP 2010" sabe que o POSCOMP é um exame de múltipla escolha com 70 questões, exigido pelos melhores programas de pós-graduação em Ciências da Computação / Engenharia da Computação / Engenharia de Sistemas / Sistemas de Informação / Informática e áreas correlatas no Brasil.

Se você pretende entrar em programas de mestrado / doutorado em computação na USP, UNICAMP, UFSCar, UNIFESP, PUC-Rio, UFRJ, UFMG, UNB, UFPE, UFPR, IME–RJ, UFRGS, UFSC, etc é recomendável prestar o exame. Esses programas geralmente usam o POSCOMP tanto na seleção de mestrandos e doutorandos quanto como critério para distribuição de bolsas.

O exame é divido em três grandes áreas: Matemática, Fundamentos da Computação (que contém a maior parte das questões) e Tecnologia da Computação.

O objetivo dos candidatos buscando vagas em programas de excelência é ficar acima da média geral. Essa é historicamente baixa. A média de acertos entre 2002 e 2011 foi de aproximadamente 25 questões (~35%). Isso mostra o nível de exigência do exame.

Eu prestei o exame em 2010. Com os resultados do exame garanti vagas em bons programas de pós-graduação, incluindo o Programa de Engenharia de Sistemas e Computação na COPPE / UFRJ e no Departamento de Informática da PUC-Rio, ambos conhecidos pela excelente produção científica e pelo conceito máximo na avaliação da CAPES.

É claro que esses programas levam em consideração muitas outras coisas além do POSCOMP. Dentre elas: histórico acadêmico, cartas de recomendação, envolvimento com atividades de pesquisa (Iniciação Científica e publicações), currículo, etc. Um fator importante é buscar uma área de pesquisa de seu interesse e, dentro dessa área, orientadores que possam guiá-lo em suas atividades de pesquisa (é costumeiro que alunos de pós-graduação sigam a linha de pesquisa de seus orientadores).

Nesse domingo (29/09/2013) voltei ao IME-USP para prestar o POSCOMP pela segunda vez. Segue a prova com gabarito oficial



Para candidatos interessados em prestar o POSCOMP em 2014, tomei a liberdade de fazer upload dos 4 últimos exames para o Scribd (extraídos do site da SBC). 


Boa sorte a todos que estão aguardando os resultados oficiais!

PS: Se você prestou o POSCOMP por favor deixe um comentário com suas impressões sobre o exame.


UPDATES

  1. Criei uma planilha no Google para estimarmos a média de 2013.
    Link: Média POSCOMP 2013
  2. Gabarito provisório substituído pelo definitivo.
  3. Planilha para correção da prova conforme gabarito definitivo.
    Link: Correção POSCOMP 2013

sábado, 21 de setembro de 2013

MOOC - Princípios de Programação Funcional em Scala

Gostaria de aproveitar esse post para divulgar um excelente curso online gratuito na Coursera.

Trata-se do curso Princípios de Programação Funcional em Scala (Functional Programming Principles in Scala). Segue link: https://www.coursera.org/course/progfun.

O instrutor do curso é ninguém menos do que Martin Odersky, criador da linguagem Scala, fundador da empresa Typesafe e Pesquisador na  École Polytechnique Fédérale de Lausanne

Eu acompanhei a segunda versão do curso fora de época e posso atestar a qualidade em primeira mão. De fato o curso da Coursera é utilizado como parte das atividades na EPFL, ou seja, alunos do Professor Odersky se matriculam normalmente na Coursera junto a outros milhares de candidatos ao redor do mundo; na primeira versão do curso mais de 50.000 pessoas se inscreveram (veja as estatísticas).

O tom do curso é bastante acadêmico, entrando em detalhes sobre modelo de substituição logo na primeira aula e navegando no mundo de funções de alta ordem, currying, covariância, contravariância, pattern matching, tuplas, parâmetros implícitos, monoides, streams, etc. Mas acredito ele seja também de grande valia para a indústria. Meus colegas de trabalho sempre me escutam tagarelando sobre Scala... Principalmente quando esbarro em pedaços de código longos e difíceis de ler em Java com contrapartidas intuitivas e sucintas em Scala. Além disso, cada vez mais linguagens Orientadas a Objetos vem adotando construções típicas de linguagens Funcionais como genéricos (introduzidos no Java 5) e expressões lambda (suportadas em C# desde a versão 3.0 e e pelo Java 8 previsto para Março de 2014). 

Nada como adicionar uma linguagem "híbrida", concebida com expressividade e escalabilidade em mente, 100% interoperável com Java (e seu enorme ecossistema) e altamente performática ao seu conjunto de skills. Além do que, aprender a mentalidade da programação funcional te faz um programador melhor em geral... Após minha experiência com Scala acabei descobrindo jóias do Apache Commons e Google Guava que possibilitam escrever código Java muito mais limpo. Também reforcei meu padrão de pensar mais / escrever menos código (os exercícios do curso realmente te fazem quebrar a cabeça, e no fim das contas as soluções são sempre simples).

O curso tem duração de sete semanas. A cada semana o aluno recebe o material de estudo (incluindo vídeos do Martin Odersky) e uma atividade de programação (com data de entrega para a próxima semana). O aluno pode submeter os exercícios através de um plugin do sbt (ferramenta de build popular entre desenvolvedores Scala). A correção dos exercícios é feita automaticamente em servidores (no Amazon EC2) que rodam testes unitários e analisadores estáticos de código contra a solução submetida. O aluno recebe uma nota de 0 a 10 e feedback sobre seu exercício  de maneira quasi-instantânea. A correção leva em consideração:
  • Testes unitários
  • Estilo (indentação, espaços em branco, etc) 
  • Boas práticas da programação funcional em Scala (evitar casts, variáveis locais mutáveis, uso de return, etc) 
  • Prazo de entrega (cada dia de atraso desconta 20% da nota)
O aluno pode submeter respostas para o mesmo exercício até cinco vezes com o objetivo de refinar sua implementação. São aprovados no curso (com direito a certificado oficial) alunos que obtiverem média acima de 60%.

Além do arsenal para correção automática de exercícios, o curso conta com um rico fórum de discussão em que alunos podem interagir, formar grupos de estudo e submeter / responder questões. Os fóruns são moderados por assistentes voluntários (comunidade) e staff oficial do curso para garantir a qualidade das discussões (bem como evitar que os alunos "colem").

A experiência do curso é muito enriquecedora, definitivamente vale a pena.

E ainda dá tempo de se matricular! A data de entrega para o primeiro exercício é dia 25/09/2013... No pior caso, se você perder essa data é possível passar no curso sem entregar o primeiro exercício (obtendo boas notas nos demais exercícios).

Então o que está esperando? Venha participar!

terça-feira, 17 de setembro de 2013

Slides- Escalabilidade Web / DevOps e PaaS

Slides da palestra "Escalabilidade Web: Sharding, Indexação, CDN, NoSQL, DevOps, Cloud, PaaS e a Vida Real" na EACH - USP Leste.

Agradeço ao Professor Eler e a todos que participaram!


domingo, 8 de setembro de 2013

Linux em 2013 - Primeiras impressões do openSUSE 12.3 e KDE 4

Recentemente, um pouco decepcionado com o Ubuntu 13.04, comecei a procurar outras distros Linux para uso no dia a dia. 

E como o cenário das distros mudou de alguns anos para cá!  Eu sou da época em que suas escolhas se resumiam a:

Não me leve a mal, já existiam várias distros voltadas a desktops e outros sistemas de arquivo além do ext, mas a vida para o típico usuário Linux costuma ser bem mais simples.
No servidor boa parte de nós rodava RHEL, seu primo CentOS ou o Debian. Para o desktop os grandes nomes eram Ubuntu e Fedora. Aqui no Brasil, nosso querido (e descontinuado) Kurumin escrito pelo Carlos Morimoto, bem como o Conectiva Linux (que, após fusão com o Mandrake, deu origem ao Mandriva Linux que deu origem ao Mangeia) fizeram muito sucesso... 

Mas nada pode parar a evolução. Foram lançados os controversos Gnome Shell e KDE 4, que desagradaram parte dos usuários acostumados com a tradicional metáfora de escritório. A Canonical lançou o Unity e começou a distribuí-lo por padrão com o Ubuntu; surgiram também outros projetos como MATE para agradar os usuários leais ao Gnome 2 e Cinnamon para quem desejava uma interface tradicional em cima do Gnome 3 (ambos distribuídos com Linux Mint, outra distro fantástica que pretendo revisar em breve). Projetos como o Xfce e LXDE, que antes viviam na escuridão também ganharam popularidade.

Eu não tenho cojones para tecer opiniões sobre a fragmentação dos ambientes de desktop Linux (nem na camada mais baixa dos display servers como X11, Wayland e Mir). Então deixo um vídeo do Bryan Lunduke, apaixonado o suficiente por Linux para cutucar a ferida:

(Assistam também Why Linux Doesn't Suck - 2013)

Enfim, com ou sem fragmentação, eu brinquei o suficiente com o Windows, OS X e primos do Linux como Solaris e FreeBSD para saber em qual SO quero desenvolver... E esse SO é o Linux! De preferência em uma distro com UI agradável e responsiva.

Fico feliz quando o sistema vem pré-instalado com o Compiz (ou similar) e tem todo o eye candy para as tarefas mundanas. Fico ainda mais feliz quando o sistema me permite desativar todos os efeitos visuais com um click ou tecla de atalho, de forma que eu possa rodar uma instância do Eclipse, outra do JDeveloper, uma terceira do SQL Developer, dois domínios do Weblogic, um terminal com 5 abas em SSH e o Chrome com 30 abas abertas sem que o sistema tenha que desperdiçar recursos com transparência e efeitos de transição (sim, estou falando sério, já trabalhei com tudo isso tudo - e muito mais - simultaneamente!). Nessas situações extremas você pode perceber a eficiência do mecanismo de memória virtual e sistema de arquivos do Linux.

Um outro fator importante para decidir entre distros é o ciclo de vida. Enquanto o suporte de 5 anos para versões LTS do Ubuntu é interessante, eu sempre preciso de algum aplicativo de versões mais novas do SO (nem sempre disponíveis através de Backports). O suporte por apenas 9 meses das versões comuns do Ubuntu é insano para uso no trabalho (infelizmente o Mint, baseado em Ubuntu, segue o mesmo ciclo de vida de 9 meses). Esse é um ponto muito positivo do openSUSE que mantém suporte por pelo menos 18 meses (na verdade, duas releases + dois meses).

Outro ponto positivo do openSUSE é a forte comunidade (não tão grande quanto a do Ubuntu ou Fedora, mas muito prestativa, educada e entusiástica) e o "apadrinhamento" pela Novell.  

Quem me conhece sabe que eu costumo torcer o nariz para distros com KDE e RPM (más experiências com o Fedora), mas a recomendação de amigos e a elegância da distribuição me levaram a experimentar algo novo (no VirtualBox é claro).

Pouco mais de uma semana após a instalação e estou tão satisfeito que em breve promoverei o SO à sua própria partição (junto ao Windows 7 - como me arrependo de ter instalado o Windows 8 - e Mint 15).

O download e instalação são muito simples (estilo next, next, next). Estão disponíveis Live CDs Gnome e KDE, bem como um DVD capaz de instalar ambos os desktops e uma vasta seleção de software (o DVD funciona como um repositório).

O boot é rápido; a interface é limpa, bem trabalhada e fluída. O KDE, na minha opinião, sempre deixou o Gnome no chinelo em termos de configuração / customização, mas sempre me pareceu demasiadamente burocrático e pesado... Não é o caso dessa versão.

Eu vou ser honesto e admitir que ainda sou, por natureza, um usuário Gnome 2 / Unity e que fico um pouco perdido com conceitos do KDE como atividades. Dito isso, para um dinossauro até que não demorei muito para me encontrar no Plasma... É tudo muito intuitivo, não leva mais de alguns minutos para descobrir e entender os painéis, widgets e folder views

Plasma

Nem me dei ao trabalho de customizar a aparência do sistema. Na verdade essa foi a distro com o tema padrão mais bonito que já encontrei (isso é, para quem gosta de preto). 

Isso não significa que não existam maneiras de personalizar papéis de parede, temas, decorações de janela, etc; inclusive os aplicativos de customização do KDE contam com botões para baixar mais recursos na internet (um bom site para começar é http://kde-look.org/)
Decorações de Janela

Outro ponto que me preocupava é se eu conseguiria instalar versões razoavelmente atuais dos softwares que uso. Para minha surpresa não senti tanta falta do gigantesco repositório do Ubuntu e seu ecossistema de PPAs. Entre os repositórios padrões do openSuse, RPMs disponíveis na internet e os típicos softwares distribuídos nos formatos bin e tar.gz encontrei tudo que precisava (Java, Scala, IDEs, versões recentes do Mercurial, Git, Maven, sbt, etc). Mesmo softwares da Oracle que historicamente sempre foram "seletivos" em relação a distros instalaram sem nenhum problema (ainda não usei todos exaustivamente, mas por enquanto tudo parece estar em ordem).

Um ponto forte do openSUSE é o mecanismo One Click Install que adiciona repositórios, verifica dependências, faz a instalação e configura atualizações automáticas para determinado software em um único passo através de botões em websites e arquivos YMP distribuídos pela internet. Combine esse mecanismo com um portal que agrega pacotes oficiais e não oficiais e você tem o melhor dos mundos.

Package Search
Falando em atualizações, essa é uma área muito transparente e funcional no openSUSE. Atualizações disponíveis aparecem na área de notificação e, caso o usuário deseje atualizar um pacote, os softwares Apper e YaST (esse último é muito superior ao Ubuntu Software Center, e, na minha opinião, mais intuitivo do que o Synaptic) se encarregam de todo o processo.
Apper
YaST
Algo admirável do KDE é a flexibilidade para customização das teclas de atalho. O ambiente oferece configurações para atalhos globais, atalhos específicos de cada aplicação e mesmo de aplicativos no menu. Olha o Alt+Shift+F12 para desabilitar os efeitos visuais aí ;).

Configuração de atalhos globais
É claro que, por melhor que uma distro seja, sempre existem alguns probleminhas:
  1. Esbarrei em um bug do kdesu quando a senha do root contém aspas duplas (")
  2. A performance do flash é abismal (mas pode ser culpa da VM)
  3. A versão do Amarok pré-instalada é muito bonita, mas achei bastante instável:
  4. Amarok
  5. Não consegui fazer o IntelliJ 13 EAP funcionar (admito que isso é pedir um pouco demais)
  6. Chrome resolveu achar que o 7u25 não é a versão mais atual do Java e bloquear o plugin (nada que um --allow-outdated-plugins não resolva, e pelos reports que li isso não tem nada a ver com o openSUSE)
Em suma: O openSUSE é uma distro rápida, polida, completa, bem documentada, com vasto apoio da comunidade e da Novell; além disso possui excelentes ferramentas de administração e um ecossistema de software de fazer inveja em muitas distros por aí. Definitivamente recomendo para trabalho e dia a dia.




domingo, 23 de junho de 2013

IDE Updates

Após longo período em hiato, segue um breve relate das novidades no mundo dos IDES Java:

O Netbeans 7.3.1 está fantástico. Definitivamente ganhou a corrida por novas features (destaque para o suporte a Java EE 7, HTML 5 e JPQL). Tratando-se de primeira impressões esse me parece ser o melhor IDE do ano.

A Early Access Preview do IntelliJ IDEA 13 também promete! Apesar do foco da nova versão ser desenvolvimento Android, tive a impressão de que o IDE está bem mais rápido no que em sua encarnação 12. Apesar do pessoal da Jetbrains alertar novos usuários de que a qualidade de versões EAP pode ser inferior a de versões Beta, achei a v13 bastante estável. Recomendo! 

Sobre o Eclipse Kepler (atualmente na versão RC3), enquanto na minha máquina (Ubuntu - 64 bits) o ambiente ficou um pouco instável (com exceções em background e freezes),  a diferença de performance em comparação ao Juno é notável. As novas versões do m2e e m2e-wtp melhoraram bastante o suporte a projetos Maven  (configurações intrusivas à parte, pela primeira vez o Eclipse parece estar se aproximando das outras IDES nesse quesito); para os usuários de Git o EGit está quase tolerável... Destaque para a força do ecossistema, com parceiros abraçando o Kepler antes mesmo da sua primeira versão estável: OEPE, JBoss Tools e STS sendo alguns dos principais exemplos.

P.S. Tive meu primeiro contato com o IntelliJ em uma versão EAP, antes da primeira versão comunitária ser lançada... Desde então comprei e renovei licenças do IDE duas vezes!

sábado, 29 de dezembro de 2012

JAR Hell - Um guia prático

O que é JAR Hell?


JAR Hell é um termo cunhado para descrever de forma genéricas problemas relacionados ao ClassLoader. Suas variações mais comuns acontecem quando:
    1. Duas ou mais classes diferentes, com o exato mesmo nome qualificado acabam sendo incluídas no projeto (e.g, duas versões diferentes da biblioteca ASM no Classpath).
    2. Duas ou mais bibliotecas no Classpath dependem de versões diferentes das mesmas classes (e.g., Hibernate e Spring dependendo de versões diferentes da biblioteca ASM).

      Sintomas do JAR Hell


      JAR Hells possuem algumas peculiaridades marcantes, mesmo assim nem sempre seu diagnóstico é óbvio; várias vezes uma situação de JAR Hell vem mixada com outros tipos de problemas como ausência de dependências transitivas no Classpath e omissões em arquivos de configuração.
      Eis alguns sintomas quem indicam um problema de JAR Hell:
      • Estão sendo disparados NoSuchMethodError, NoSuchFieldError ou IllegalAccessError.
      • ClassCastException entre classes iguais ou compatíveis.
      • Problemas de serialização / deserialização.
      Outra pista que aponta para uma situação de JAR Hell acontece quando um ou mais dos problemas mencionados acontecem de forma intermitente, e particularmente quando dão a impressão de estarem relacionados a questões de build / ambiente (e.g., aparecem no ambiente de homologação mas não no de desenvolvimento; builds pelo IDE funcionam / builds pela ferramenta de Integração Contínua não; com o servidor em modo de desenvolvimento tudo funciona mas em modo de produção não; com JVMs da Sun tudo funciona e com JRockit não).
      Isso ocorre pois quando há duas ou mais classes com o mesmo nome qualificado no Classpath, a lógica que determina qual delas será carregada fica codificada no ClassLoader utilizado, ou em última instância, na lógica dos ClassLoaders de base da própria JVM. 
      Prever qual versão de uma classe será carregada é uma tarefa difícil devido a cadeia complexa de ClassLoaders tipicamente presente em soluções enterprise. O próprio ClassLoader escolhido para abrir determinada classe pode variar conforme o estado do container e código da aplicação. 
      Em geral o ClassLoader que carrega uma classe também fica responsável por carregar todas as outras classes utilizadas por ela; essas classes e o valor de suas variáveis estáticas são então cacheados em memória (e.g., na famigerada PermGen). Isso significa que - salvo exceções em que o ClassLoader se torna elegível para Garbage Collection e a JVM é otimizada para fazer unloading de classes - uma vez que determinada versão de uma classe seja carregada ela permanece em memória, em um namespace relacionado ao ClassLoader, até fim do processo.

      Resolvendo Problemas de JAR Hell


      Os passos lógicos para resolver JAR Hells são:
      • No caso de classes duplicadas dentro do domínio da sua aplicação: Detectar e excluir versões antigas da classe duplicada. Preferencialmente deixar somente uma classe de cada tipo no Classpath, i.e., não há necessidade da mesma classe estar presente em vários JARS da aplicação, sendo recomendável refatorar as classes repetidas para um JAR a parte.
      • No caso de incompatibilidade entre bibliotecas de terceiros: Fazer upgrades e / ou downgrades das bibliotecas para uma combinação com dependências transitivas compatíveis. Uma ferramenta para gerenciar dependências ajuda muito.
      Se por algum motivo não for possível eliminar versões duplicadas de uma classe ou encontrar bibliotecas compatíveis, como último recurso é possível escrever ClassLoaders personalizados. Esse é um tópico avançado que fico devendo para um próximo post. Classifico o uso de ClassLoaders customizados como um último recurso pois eles aumentam a Entropia do Software, são de difícil manutenção e, se não forem bem arquitetados, podem gerar todo tipo de problemas (NoClassDefFoundError, java.lang.OutOfMemoryError: PermGen space, etc).

      Encontrando classes duplicadas


      Geralmente essas classes estão em bibliotecas do EAR (APP-INF/lib), WAR (/WEB-INF/lib), ou do Servidor de Aplicação.
      Para saber de que JAR / diretório determinada classe está sendo lida utilize os seguintes métodos:
      public static URL getLocation(Class clazz) {
          return clazz.getProtectionDomain().getCodeSource().getLocation();
      }
      public static URL getLocation(String className) 
          throws ClassNotFoundException {
          return getLocation(Class.forName(className));
      }
      Exemplos de chamada e resposta (para um projeto mavenized):
      System.out.println(getLocation(EntityManager.class)); 
      /* 
       * file:/home/anthony/.m2/repository/javax/persistence/
       * javax.persistence/2.0-SNAPSHOT/javax.persistence-2.0-SNAPSHOT.jar 
       */
      System.out.println(getLocation(
          "org.apache.commons.lang.builder.ReflectionToStringBuilder")); 
      /* 
       * file:/home/anthony/.m2/repository/commons-lang/commons-lang/
       * 2.6/commons-lang-2.6.jar 
       */
      Um bom lugar a ser analisado são clientes de Web services gerados automaticamente, principalmente quando mais de um serviço depende do mesmo XSD. Nesse cenário é comum que vários clientes sejam gerados a partir de WSDLs diferentes, todos contendo suas próprias versões da mesma classe. 
      Na verdade todo tipo de código gerado automaticamente merece atenção: Classes JAXB geradas com xjc, entidades JPA repetidas em diferentes projetos EJB, etc. 

      Problemas de compatibilidade entre bibliotecas de terceiros


      Para resolver esse tipo de JAR Hell é necessário encontrar versões compatíveis das bibliotecas (e.g., uma versão do Spring e do Hibernate que possam funcionar com a mesma versão da biblioteca ASM), ou, em casos de total incompatibilidade, escrever ClassLoaders customizados.
      Geralmente esse tipo de erro acontece com bibliotecas populares como como Apache Commons, Javassist e ASM que são dependências para uma grande quantidade de frameworks e bibliotecas.
      Devido a dependências transitivas (e.g., seu projeto depende da biblioteca A que por sua vez depende da biblioteca B que depende da biblioteca C e assim sucessivamente), encontrar versões compatíveis de bibliotecas pode se tornar uma tarefa enfadonha.  
      Para aliviar o trabalho do programador ferramentas poderosas como Maven, Ivy e Buildr estão disponíveis. Com essas ferramentas é possível especificar as bibliotecas (e versões / intervalos de versões) que seu projeto necessita em arquivos de configurações; essas ferramentas fazem então o download dos artefatos - e suas dependências transitivas - a partir de uma hierarquia de repositórios de software (como o gigantesco Repositório Central), ajustam o Classpath da aplicação para compilação / execução / testes e ainda empacotam bibliotecas dentro dos EARs, WARs, etc para distribuição quando cabível. 
      Caso ocorra algum conflito o desenvolvedor pode trocar facilmente a versão de determinada biblioteca no arquivo de configuração e deixar que a ferramenta faça o trabalho duro por ele.
      Enquanto uma ferramenta como o Maven não se aplica a todo tipo de projeto (pois introduz suas próprias complexidades), eu costumo usá-lo pelo menos para fazer download das dependências do projeto e exportá-las com o Dependency plugin. Fico devendo um tutorial sobre esse assunto para um próximo post.

      Bibliotecas do Servidor de Aplicação vs Bibliotecas do Projeto


      Pessoalmente tento, sempre que possível, usar bibliotecas do próprio servidor (que passaram por todo o processo de homologação do Java EE, e, por via de regra - mas não como verdade absoluta - são compatíveis). Para esclarecer, não estou pedindo para ninguém abrir mão das bibliotecas (por favor, reuso na cabeça!), apenas recomendo pesquisar se o próprio servidor de aplicação já não fornece uma versão da biblioteca desejada ou algo equivalente (e.g., Hibernate x Eclipselink para JPA).
      Não se preocupe em sempre incluir a versão bleedin edge de uma biblioteca no projeto. Geralmente as versões disponibilizadas pelo Application Server são mais do que suficientes (salvo exceções em lugares que ainda estão rodando Application Servers homologados para versões anteriores ao Java EE 5). Minha experiência nesse ponto é que quando você coloca uma biblioteca bleedin edge no projeto ela acaba permanecendo lá por mutos anos e eventualmente se torna legada (ninguém quer mexer em bibliotecas da aplicação por motivos óbvios, incluindo JAR Hells), enquanto que ao fazer referência as bibliotecas do App Server, a evolução vem lenta porém certamente conforme upgrades planejados para versões mais novas do container.
      Enquanto há bons argumentos contra depender do container (e.g., reduzir o trabalho de infraestrutura ao fazer deploy das bibliotecas; ter menos problemas ao fazer upgrade do servidor de aplicação e ter mais controle sobre o que está sendo utilizado no projeto), eu pessoalmente acho que é um trade-off válido.
      Eis um exemplo de como referenciar uma biblioteca no weblogic-application.xml (EAR).
      <wls:library-ref>
          <wls:library-name>jersey-bundle</wls:library-name>
          <wls:specification-version>1.1.1</wls:specification-version>
          <wls:implementation-version>1.1.5.1</wls:implementation-version>
      </wls:library-ref>
      Fico devendo exemplos de sobre como referenciar bibliotecas no JBoss AS, GlassFish, WebSphere, etc.

      Na verdade, como deixei muitos pontos em aberto nesse post (como escrever um ClassLoader, como exportar dependências do Maven e como referenciar bibliotecas nos principais servidores de aplicação), aceito sugestões sobre o tema de posts futuros. Por favor deixem seu comentário ou enviem uma mensagem através do formulário de contato.