tag:blogger.com,1999:blog-9562465685704088222024-03-14T06:58:39.771-03:00Dev@MapsDev@Mapshttp://www.blogger.com/profile/06230808609848978162noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-956246568570408822.post-89623528475752174652011-12-08T18:30:00.001-02:002011-12-08T18:41:27.611-02:00<b><span class="Apple-style-span" style="font-size: large;">JavaOne 2011 - Latin America</span></b><br />
<br />
Apresentamos neste JavaOne uma palestra chamada: "Entendendo ClassLoaders: Dificuldades e Soluções" onde falamos como funcionam os class loaders e, principalmente, como funcionam os class loaders em servidores de aplicações e aplicativos web.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwv_INcZHFY-FEKecpdWNYgzc8VSFu6IQTR46sVDWFBzo8aZkI76RTCzsaIEIyrrtFn7yT7XCiVmWosBpXODlLX3Zl94s3YiJxE3d1TP2sqIhrA0LlGk7z7hQZR_rlkEg6_kpx_LNaSLhQ/s1600/20111207_111012.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwv_INcZHFY-FEKecpdWNYgzc8VSFu6IQTR46sVDWFBzo8aZkI76RTCzsaIEIyrrtFn7yT7XCiVmWosBpXODlLX3Zl94s3YiJxE3d1TP2sqIhrA0LlGk7z7hQZR_rlkEg6_kpx_LNaSLhQ/s320/20111207_111012.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sala cheia e gente de pé</td></tr>
</tbody></table>
<br />
Os slides da palestra podem ser vistas <a href="http://code.google.com/p/mapsdev/downloads/detail?name=ClassLoaders.pdf&can=2&q=">aqui</a>.<div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-19082294942001066822011-10-07T01:50:00.002-03:002011-10-07T03:00:36.674-03:00JavaOne 2011 Day 5Hoje foi o ultimo dia do JavaOne 2011. O dia abriu com um keynote da IBM antes da Community Keynote. O representante da Oracle (<a href="http://www.cloudjason.com/">Jason McGee</a>) falou bastante sobre o cloud e como a IBM (e o comite do JEE) pretende facilitar a vida dos desenvolvedores Java. McGee tambem citou um GC diferente chamado <a href="http://www.ibm.com/developerworks/websphere/techjournal/1108_sciampacone/1108_sciampacone.html">Balance Collector</a> que me pareceu interessante e estara disponivel no JDK7 do J9 (a JDK da IBM) para ser usado em sistemas com heaps muito grandes. McGee tambem reenforcou o comprometimento da IBM com Java ha muito tempo (e mais recentemente, quando eles entraram no OpenJDK). O KeyNote da IBM se seguiu com 1 minuto de silencio pela morte de Steve Jobs e em seguida, Donald Smith convidou membros da comunidade para subirem no palco e participar de um painel. O painel contom com, entre outras pessoas, <a href="http://www.java.net/pub/au/88">Bruno Souza</a> (do <a href="http://soujava.org.br/">SouJava</a>) <a href="http://martijnverburg.blogspot.com/">Martijn Verburg</a> (do London User Group e da session Diabolical Developer) e focou, principalmente, na comunidade e as dificuldades de se manter um JUG com varias pessoas participando (e sempre que vejo paineis como esse, sinto-me um pouco culpado pela minha baixa participacao). Por ultimo, 3 dos 4 membros do JavaPosse subiram ao palco e conduziram varias pesquisas com a plateia e as technical session comecara.<div><br /></div><div><span class="Apple-style-span"><b>Do You Really get ClassLoaders? - <span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=37134&ts=1317965078767" style="color: rgb(0, 85, 170); text-decoration: underline; ">Jevgeni Kabanov</a> da Zero Turn Around</span></b></span></div><div>Honestamente achei que a palestra seria bem mais profunda do que foi. Jevgeni explicou o basico sobre classloaders e como eles funcionam em um ambiente JEE (mostrando varios exemplos bem didaticos) e explicando porque classloaders nao sao facilmente coletados. E como nao poderia deixar de ser, fez propaganda sobre o novo produto da Zero Turn Around - Live Rebel.</div><div><br /></div><div><span class="Apple-style-span"><b>The Art Of Java Benchmark - <span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=46325&ts=1317965258395" style="color: rgb(0, 85, 170); text-decoration: none; ">Aleksey Shipilev</a> e </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=38802&ts=1317965258395" style="color: rgb(0, 85, 170); text-decoration: underline; ">Dave Keenan</a> da Oracle</span></b></span></div><div>Palestra muito interessante, mostrando as principais tecnicas para se fazer micro-benchmarks bem como os principais obstaculos (visiveis ou nao). Aleksey tambem falou em como deve se saber exatamente o que se deseja descobrir com um experimento antes de faze-lo para evitar o erro tipo III - errar a direcao da causa e efeito - encarando os benchmarks como experimentos cientificos - inclusive dando bastante enfase em interpretar corretamente os resultados.</div><div>Tambem deve se tomar cuidado para que a infraestrutura do benchmark nao interfira no benchmark propriamente dito. Talvez uma das melhores palestras sobre benchmarking que eu jah vi.</div><div><br /></div><div><b><span class="Apple-style-span">LMAX Disruptor: High-Performance Concurrent Programming Framework -<a href="http://mechanical-sympathy.blogspot.com/">Martin Thompson</a> e <a href="http://mechanitis.blogspot.com/">Trisha Gee</a> da LMAX</span></b></div><div>Ja tinha ouvido falar do <a href="http://martinfowler.com/articles/lmax.html">LMAX Disruptor antes</a>, mas esta foi a primeira vez que eu ouvi a explicacao completa de como ele foi concebido. A palestra foi um pouco estranha pelo formato (os palestrantes alternavam perguntas entre eles e mantinham um dialogo), mas o conteudo foi otimo. Martin explicou o que significa mechanical sympathy: uma maneira de programar, levando em consideracao como o hardware funciona (caches, pipelines, memoria, etc), mudando bastante o conceito de como pensar no design de um software. Por sorte, muito do que ajuda o hardware a fazer um bom trabalho pode ser considerado tambem boas praticas de desenvolvimento: classes e metodos pequenos e especializados e codigo simples. Martin tambem desafiou a nocao de que precisamos desenvolver softwares que sao executados em paralelo para obtermos performance - por exemplo, com os processadores atuais, podemos executar 3 bilhoes de instrucoes por segundo. Por ultimo, eles mostraram como funciona o <a href="http://code.google.com/p/disruptor/">disruptor</a>:</div><div>-alguns processos (com uma thread cada) trabalham em cima de alguns <a href="http://en.wikipedia.org/wiki/Circular_buffer">ring buffers </a>sem locks e sem sincronizar explicitamente os dados entre eles</div><div>-como os dados se encontram num ring buffer em arrays (que nao sao explicitamente descartados), quase todo os dados ficam nos caches da CPU e podem ser rapidamente acessados quando necessarios, diminuindo os cache misses</div><div>-quando um consumidor nao consegue consumir dados rapido o suficiente, o produtor comeca a ser pressionado, diminuindo a sua velocidade</div><div>Embora essa arquitetura tenha funcionado muito bem para eles (bem como para outros casos de uso que eles investigaram), eh uma estrategia bem agressiva e para usos bem especificos - basicamente para casos em que eh necessario um sistema de filas com latencia muito baixa e vazao muito alta.</div><div><br /></div><div>A ultima palestra que eu assisti no dia foi meio estranha (pouca relacao com java e nao tao tecnica), falando sobre o CouchBase - uma juncao do CouchDB com MemCache e seu uso em jogos sociais (da <a href="http://www.zynga.com/">Zynga </a>e da <a href="http://www.hiroku.com/">Hiroku</a>). Por ultimo, o palestrante mostrou o case da <a href="http://www.tribalcrossing.com/">Tribal Crossing</a>, uma empresa que desenvolve softwares para plataformas sociais e migrou do MySQL para CouchBase.</div><div><br /></div><div><b><span class="Apple-style-span">Conclusao</span></b></div><div>Achei um otimo evento em geral. Conversei com pessoas interessantes e algumas pessoas notaveis (Charles Nutter, Charlie Hunt, etc), aprendi muita coisa e conheci muitas ferramentas e tecnicas que provavelmente serao muito uteis. Espero honestamente que possamos participar como palestrantes da proxima vez.</div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-12717101720618209292011-10-05T23:29:00.003-03:002011-10-06T01:02:14.478-03:00JavaOne 2011 Day 4Penultimo dia do evento, hoje nao houve keynote de abertura e as technical sessions terminaram um pouco mais cedo. Antes de escrever sobre elas, vou escrever sobre duas sessoes que eu nao escrevi ontem.<div><br /></div><div><span class="Apple-style-span" ><b>Meet the JavaPosse - The JavaPosse team</b></span></div><div>O <a href="http://javaposse.com/">JavaPosse</a> eh um podcast sobre desenvolvimento, principalmente centrado em java (nao soh a linguagem como todo o ecossistema que o cerca). Eh produzido por um grupo de desenvolvedores que tem ou em algum momento da carreira, tiveram grande contato com java e trabalharam em grandes empresas como Sun, Google, Applet, Netflix, etc. Eu aconselho fortemente a todos os desenvolvedores java que oucam o podcast (se eu nao me engao, eh publicado uma vez a cada 2 semanas).</div><div><br /></div><div><b><span class="Apple-style-span" >The Heads and Tails of Project Coin - <a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=47800&ts=1317870109589">Joseph Darcy</a> da Oracle</span></b></div><div>Esta palestra foi bem simples e basicamente explicou as funcionalidades implementadas no <a href="http://openjdk.java.net/projects/coin/">project Coin</a>, detalhes de implementacao e tambem o que esta por vir na continuacao do project Coin no JK8 e JDK9 - dessa vez, porem, eles nao estao aceitando sugestoes e vao implementar as as sugestoes feitas anteriormente.</div><div><br /></div><div>Com isso, seguem as technical sessions de hoje:</div><div><br /></div><div><span class="Apple-style-span" ><b>Blood from Stone: Low-Level HotSpot Flags for Optimization Nuts - Charles Oliver Nutter da Engine Yard</b></span></div><div>Esta palestra tambem poderia ser chamada: bytecode for dummies. Charles N. basicamente mostrou como funciona o JIT (tanto o client compiler quanto o server e o tiered), mostrando flags que podem ser ligadas em JVM's de producao e de debug para <a href="http://wikis.sun.com/display/HotSpotInternals/PrintAssembly">verificar o codigo de maquina gerado pelo HotSpot</a> e diagnosticar porque um codigo nao esta sendo executado na velocidade que deveria. Por ultimo, Charlie mostrou um problema que ele estava enfrentando no codigo do JRuby que gerava problemas de performance, mesmo conhecendo pouco sobre o assembly gerado. Nao sei se estas tecnicas se aplicam a softwares "end-user" (mesmo o Charles nao confirmou com certeza), mas deve ser aplicar pelo menos nas bibliotecas basicas.</div><div><br /></div><div><b><span class="Apple-style-span" >Rethinking How We Think About Parallel Programming - Nelson Chamberlain</span></b></div><div>Infelizmente a palestra para a qual eu estava originalmente agendado tinha se esgotado (e quem reservou, deve chegar com 15 minutos de antecedencia para garantir a reserva), entao assisti esta palestra. Nelson Chamberlain eh um professor de faculdade que esta tentando criar um metafora melhor para programacao paralela dado o fato de que nossos cerebros funcionam (normalmente) de maneira serial e fazemos varias tarefas simultanes da mesma maneira que um computador monoprocessado: atraves de <a href="http://en.wikipedia.org/wiki/Preemption_(computing)#Time_slice">time slices</a>. Logo depois de explicar como o cerebro funciona, Prof. Nelson comecou a mostrar uma metafora com o ciclo de vida dos animais (nascer, "viver", reproduzir e morrer), para depois expandir a metafora para um quase paradigma novo de programacao, implementado no <a href="http://avian.sourceforge.net/">Avian Project</a>. Honestamente achei o paradigma novo muito parecido com o que <a href="http://en.wikipedia.org/wiki/Erlang_(programming_language)">Erlang </a>promove na sua <a href="http://en.wikipedia.org/wiki/Actor_model">arquitetura de Actors e passagem de mensagens</a>. O projeto, porem, esta ainda em um estagio muito imaturo e esta a procura de contribuidores.</div><div><br /></div><div>No proximo horario, nao havia nenhuma palestra particularmente interessante, entao achei a seguinte:</div><div><br /></div><div><b><span class="Apple-style-span" >Get Physical! An Arduino Introduction for Java Developers<span class="Apple-style-span" > - <span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=18181&ts=1317871676932" style="color: rgb(0, 85, 170); text-decoration: none; ">David Delabassee</a> da Oracle</span></span></span></b></div><div>Arduino eh um micro controlador programavel opensource e de baixo custo que esta se tornando muito popular para quem quer fazer prototipos, dada a sua facilidade de programacao bem como a extensibilidade. Para programar para o Arduino, deve se usar uma linguagem de baixo nivel, mas o kit de desenvolvimento possui o conjunto completo de ferramentas para quem quiser desenvolver. Achei a palestra muito interessantes, embora tenha pouca conexao com java (o palestrante mencionou usar java para processar dados antes de enviar para o Arduino, que possui um processador bem fraquinho). </div><div><br /></div><div><b><span class="Apple-style-span" >The Diabolical Developer - Martin Verburg da London Java User Group</span></b></div><div>Nao sei direito o que escrever sobre esta palestra - assim como nao sabia o que esperar dela pelo titulo. Achei bem divertida, mas pouco informativa - o palestrante usa uma linguagem bem sarcastica para mostrar alguns pontos que, no fim das contas, nao passam de bom senso. Alguns pontos notaveis:</div><div>-pessoas sobre processos</div><div>-nao cair no hype da atualidade (hoje eh cloud)</div><div>-simplificar ao inves de complicar</div><div>Confesso que, embora tenha achado a palestra interessante, provavelmente nao assistirei a mais nenhuma dessas.</div><div><br /></div><div><b><span class="Apple-style-span" >Attack on Scaling: Methods and Tools for Eradicating Performance Bottlenecks - Charlie Hunt da Oracle e Aleksey Ignatenko da Intel</span></b></div><div>Ultima palestra do dia, esta palestra mostrou as principais causas de problemas de escalabilidade (locks e alocacao de memoria, basicamente) e como elas se manifestam (false sharing, true sharing, cache eviction). Os palestrantes mostraram tambem algumas ferramentas para detectar tais problemas: <a href="http://software.intel.com/en-us/articles/intel-vtune-amplifier-xe/">vTune da Intel</a> e <a href="http://download.oracle.com/docs/cd/E18659_01/html/821-1379/index.html">Oracle Solaris Performance Analyzer</a>. Tais ferramentas sao capazes de mostrar eventos especificos da CPU (como <a href="http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBoQFjAA&url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FCycles_per_instruction&ei=tCaNTsOUOfKrsALY5qCPAQ&usg=AFQjCNH8hm4BB6oOZhOXOzDLAZbtPd9g_w">CPI</a>, <a href="http://en.wikipedia.org/wiki/CPU_cache#Cache_Misses">cache misses</a>, etc) e liga-los ao codigo java que os gerou, possibilitando diagnosticar os problemas diretamente na CPU.</div><div><br /></div><div>Aproveitei o dia curto para falar com mais exibidores - particularmente falar com o pessoal do JRockit para ver um demo da ferramenta de diagnostico de performance deles chamado <a href="http://www.oracle.com/technetwork/middleware/jrockit/overview/index-090630.html">Mission Control</a>. Fiquei bem impressionado com o que vi e com certeza darei uma olhada nele quando puder.</div><div><br /></div><div><div>PS: Ontem esqueci de postar, mas o<a href="http://www.oracle.com/javaone/lad-en/home/index.html"> JavaOne Latin America</a> esta confirmado para os dias 6 a 8 de Dezembro em Sao Paulo.</div></div><div><br /></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-36996881047556302902011-10-05T01:30:00.003-03:002011-10-05T03:13:12.267-03:00JavaOne 2011 Day 3<span class="Apple-style-span">O dia comecou como os outros: com um keynote de abertura ministrado novamente por Adam Messinger que infelizmente nao consegui assistir. Mas conversei com muita gente e o keynote foi bem simples e com poucas surpresas - muitas pessoas comentaram que parecia uma conversa feita para os acionistas da Oracle ao inves de desenvolvedores. Algumas coisas, porem, foram anunciadas:</span><div><span class="Apple-style-span">-teremos uma versao nova do java a cada 2 anos (ao inves dos 18 meses planejados ateh hoje) - a Oracle percebeu que nao era possivel entregar todas as funcionalidades planejadas em intervalos de 18 meses. Desse modo, teremos o JDK8 (com <a href="http://openjdk.java.net/projects/lambda/">lambda</a>, <a href="http://www.wiki.jvmlangsummit.com/images/a/a1/2011_Goetz_Extension_Slides.pdf">virtual extension methods</a> e outras coisas) em meados de 2013 e JDK9 (<a href="http://openjdk.java.net/projects/jigsaw/">jigsaw</a>, <a href="http://classparser.blogspot.com/2010/03/coroutines-for-java-status-update.html">coroutines</a>, <a href="http://gafter.blogspot.com/2006/11/reified-generics-for-java.html">generics reificados</a>, entre outras coisas) em meados de 2015.</span></div><div><span class="Apple-style-span">-Twitter entrou no JDK e no JCP, muito provavelmente para melhorar o suporte da JVM em outras linguagens</span></div><div><span class="Apple-style-span"><br /></span></div><div><span class="Apple-style-span">Com isso, vamos direto as Technical Sessions:</span></div><div><span class="Apple-style-span"><br /></span></div><div><span class="Apple-style-span"><b><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Everything I Ever Learned About JVM Performance Tuning at Twitter - </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=203207&ts=1317790585903" style="text-decoration: underline; "><span class="Apple-style-span">Attila Szegedi</span></a> do Twitter</span></b></span></div><div><span class="Apple-style-span">A palestra falou basicamente das diferentes opcoes de 'tunning' da JVM para minimizar, principalmente, a latencia e tempo de resposta das aplicacoes. Attila mostrou os diferentes tipos de GC, como as classes e objetos "ocupam" espaco na memoria e o que pode ser feito para minimizar o uso de memoria (inclusive em casos extremos). O palestrante tambem frisou que eh muito importante fazer profiling mesmo de bibliotecas largamente utilizadas - por exemplo, o twitter enfrentou alguns problemas com Thrift e a biblioteca padrao de scala. Por ultimo, foram sugeridas algumas configuracoes que podem ser feitas em relacao ao GC.</span></div><div><span class="Apple-style-span"><br /></span></div><div><span class="Apple-style-span"><b><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Real Java Enterprise Testing - </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=49444&ts=1317791969472" style="text-decoration: none; ">Aslak Knutsen</a> e </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=46140&ts=1317791969472" style="text-decoration: none; ">Dan Allen</a> da Red Hat</span></b></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span">Esta apresentacao foi um showcase para o <a href="http://www.jboss.org/arquillian">projeto Arquillian</a> (e demais projetos). Este framework parece muito promissor para testar o comportamento de uma aplicacao em diversos ambientes diferentes (WAS, JBossAS, Tomcat) de forma automatizada. O framework se integra com o JUnit, eh capaz de pegar arquivos gerados pelo maven e fazer o deploy de mais de um sistema e em mais de um servidor de aplicacoes.</span></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span"><br /></span></span></div><div><span class="Apple-style-span"><b><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Blazing JVM Performance: Trends Fueled by the Latest Hardware and JVM Optimizations - </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=21960&ts=1317792870171" style="text-decoration: underline; ">Shirish Aundhe</a> da Intel e </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=38802&ts=1317792870171" style="text-decoration: underline; ">Dave Keenan</a> da Oracle</span></b></span></div><div><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Esta palestra expandiu um pouco o keynote da Intel de ontem, falando um pouco sobre a parceria entre a Intel e a Oracle, falando um pouco sobre como as novas instrucoes dos processadores influenciam o desenvolvimento da JVM e como a JVM se beneficia (ou nao) das novas instrucoes, como vetorizacao de loops internos e otimizacoes de operacoes de ponto flutuante. Eles tambem mostraram como pequenas otimizacoes na bibliotecas podem influenciar o uso do <a href="http://en.wikipedia.org/wiki/CPU_cache">cache do processador</a>. </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Por ultimo, o engenheiro da Oracle mostrou algumas flags "escondidas" da JVM que ligam otimizacoes ainda nao totalmente testadas - como por exemplo, -XX:+AgressiveOpts (ativa otimizacoes mais agressivas), -XX:+UseCompressedStrings (comprime Strings para array de bytes quando possivel), etc.</span></span></div><div><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><br /><span class="Apple-style-span"><b>Squashing the Vulnerabilities: Engineering Security into Your Applications - </b></span></span><b><span class="Apple-style-span"><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=48801&ts=1317793349669" style="text-decoration: none; ">James Gould</a> e </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=49042&ts=1317793349669" style="text-decoration: none; ">Lin Jia</a> da Verisign</span></span></b></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Os palestrantes mostraram algumas das principais vulnerabilidades que sao introduzidas em um sistema de maneira nao intencional, bem como maneiras de configurar o <a href="http://download.oracle.com/javase/tutorial/essential/environment/security.html">Security Manager</a> para isolar funcionalidades que precisam de permissoes especiais. </span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><br /></span></div><div><span class="Apple-style-span"><b><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">How Do You Update Your Java EE App in Production? - </span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=37134&ts=1317793863180" style="text-decoration: underline; ">Jevgeni Kabanov</a> CTO da Zero TurnAround</span></b></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span">Era para ser um <a href="http://en.wikipedia.org/wiki/Birds_of_a_Feather_(computing)">BOF</a>, mas acabou mais sendo uma sessao de pesquisa sobre atualizacao de aplicacoes, com um pouco de propaganda do <a href="http://www.zeroturnaround.com/liverebel-page/">LiveRebel </a>no final. O produto me pareceu bem interessante e tem potencial para acabar (ou pelo menos diminuir drasticamente) as dificuldades de se atualizar um sistema em producao.</span></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span"><br /></span></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span"><b>Oracle Java SE: VM and Performance Technologies - Com o time de Performance do Hotspot e JRockit</b></span></span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span">Este foi bem um Q&A com o time responsavel pela performance do HotSpot e do JRockit. Foi uma sessao muito legal, explicando varias nuances do GC (que merecem um artigo proprio em algum momento) e como o <a href="http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html">JRockit Mission Control</a> pode ajudar a detectar problemas de performance mesmo em sistemas em producao.</span></span></div><div><span class="Apple-style-span"><br /></span></div><div><span class="Apple-style-span">PS: eu nao sei o que esta acontecendo com a formatacao do blog, mas os artigos ficam sempre diferentes de como eu estou editando...</span></div><div><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span">PS2: finalmente descobri o que o JHome tem a ver com a GlobalCode - mas vou apenas linkar para este <a href="http://blog.globalcode.com.br/2011/10/globalcode-recebe-o-dukes-choice-awards.html">artigo no blog deles</a>.</span></span></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com1tag:blogger.com,1999:blog-956246568570408822.post-84874635678794479292011-10-04T01:21:00.004-03:002011-10-04T03:22:30.348-03:00JavaOne 2011 Day 2<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_x4gd3MOzmgaWpFxvMujt2g-7W41RE4We4bHK7I1dkt2dGPh2yKj1uq-V8EJRbugA9jdn-EALnZTX3v-kTmDtUHUq2ebGAVY9ekD61ZACfxK-ZWAc3Fc41Rvc4qL1fo3lNY-cWm8Cg5yU/s1600/IMG_20111003_081923.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 192px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_x4gd3MOzmgaWpFxvMujt2g-7W41RE4We4bHK7I1dkt2dGPh2yKj1uq-V8EJRbugA9jdn-EALnZTX3v-kTmDtUHUq2ebGAVY9ekD61ZACfxK-ZWAc3Fc41Rvc4qL1fo3lNY-cWm8Cg5yU/s320/IMG_20111003_081923.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5659505981831787730" /></a><br /><div>Hoje foi o dia que realmente comecou o JavaOne 2011 - que comecou com um keynote em um auditorio lotado e com mais 2 auditorios de backup - onde os keynotes estavam sendo transmitidos simultaneamente para quem nao conseguiu espaco no auditorio principal. Um pouco antes de comecar, os teloes do auditorio mostravam os vencedores do <a href="http://www.java.com/en/dukeschoice/">Duke's Choice Awards</a> desse ano (um premio dado a diversos projetos inovadores escolhidos pela comunidade), entre eles o projeto jHome que de alguma forma esta ligado a Globalcode (mas nao consegui nenhuma informacao extra).</div><div><div><br /></div><div><a href="http://www.oracle.com/javaone/live/index.html"><span class="Apple-style-span" >Keynote de Abertura</span></a></div><div>O keynote eh iniciado por Adan Messinger (embora o anunciador tenha chamado Richard Bair, o que ficou bem estranho) falando um pouco sobre a plataforma e sobre java no cloud (mais sobre isso no final), para logo depois chamar um diretor da Intel para falar sobre o relacionamento entre a Sun/Oracle e a Intel - uma cooperacao que vem melhorando tanto o hardware quanto a JVM. Tambem foi anunciado o <a href="http://blogs.oracle.com/javaone/">JavaOne blog</a>. Por ultimo, foi anunciado um produto da Oracle que eu nao esperava: o <a href="http://www.oracle.com/technetwork/database/nosqldb/overview/index.html">Oracle NoSQL Database</a> - um banco de dados <a href="http://en.wikipedia.org/wiki/NoSQL">NoSQL</a>.</div><div>Logo depois, subiu ao palco Marc Reinhold - basicamente o chefe do JavaSE - falando sobre as features do java 7 e as features propostas do java 8 e java 9 e para anunciar que daria mais detalhes sobre essas versoes no keynote de estrategia de amnha. Sobe no palco, finalmente, Richard Bair para anunciar a <a href="http://javafx.com/">disponibilidade da versao 2.0 do JavaFX</a> (apenas para windows por enquanto) e a disponiblidade de uma versao beta do netbeans com suporte ao mesmo. Logo depois, foi a vez de Linda DeMichiel falar sobre JavaEE e as facilidades do JavaEE7 para o cloud, bem como pequenas melhorias na spec. Por ultimo, sobe ao palco <span class="Apple-style-span" style="font-family: Arial, Verdana, Helvetica, sans-serif; line-height: 18px; background-color: rgb(251, 251, 251); "><span class="Apple-style-span" >Hinkmond Wong para falar sobre JavaME e metade do auditorio deixa a sala (para ser justo, o keynote jah estava 10 minutos alem do tempo previsto), mostrando que JavaME eh, provavelmente, irrelevante atualmente. </span></span></div></div><div><span class="Apple-style-span" style="font-family: Arial, Verdana, Helvetica, sans-serif; line-height: 18px; background-color: rgb(251, 251, 251); "><span class="Apple-style-span" ><br /></span></span></div><div><span class="Apple-style-span" style="font-family: Arial, Verdana, Helvetica, sans-serif; line-height: 18px; background-color: rgb(251, 251, 251); "><span class="Apple-style-span" >Com isso, iniciaram-se as technical sessions:</span></span></div><div><span class="Apple-style-span" style="font-family: Arial, Verdana, Helvetica, sans-serif; line-height: 18px; background-color: rgb(251, 251, 251); "><span class="Apple-style-span" ><br /></span></span></div><div><span class="Apple-style-span" ><span class="Apple-style-span" style="font-family: Arial, Verdana, Helvetica, sans-serif; line-height: 18px; background-color: rgb(251, 251, 251); ">Arquillian the Extensible Enterprise Platform - </span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=49444&ts=1317707288255" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: underline; ">Aslak Knutsen</a> e </span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=46140&ts=1317707288255" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: none; ">Dan Allen</a> da RedHat</span></span></div><div>Os palestrantes mostraram o <a href="http://www.jboss.org/arquillian">Arquillian</a>, uma plataforma de testes extensivel vencedora de um Duke's Choice Award que permite executar testes nos servidores de aplicacao (iniciando e fazendo deploy, se necessario). Achei a ideia muito interessante e algo que definitivamente olharei com mais cuidado - tambem irei assistir a demonstracao completa amanha). Integra as ferramentas normais de teste (JUnit e TestNG) e ainda pode ser integrado ao maven.</div><div><br /></div><div><span class="Apple-style-span" >Coroutines for the JVM - <span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=42088&ts=1317707646990" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: none; ">Lukas Stadler</a> da </span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); ">Johannes Kepler University, Linz, Austria</span></span></div><div>Coroutines (tambem conhecido como <a href="http://ruby-doc.org/core-1.9/Fiber.html">fibers em ruby</a> ou <a href="http://wiki.python.org/moin/Generators">generators em python</a>) eh uma forma limitada de <a href="http://en.wikipedia.org/wiki/Continuation-passing_style">continuations</a>. Resolvi ver como essa feature foi implementada em Java (que nao possui maneiras nao nativas de manipular o stack) e como essa features poderia ser aproveitada. O palestrante mostrou que conseguiu implementar uma versao praticamente sem limitacoes (inclusive com transporte de coroutines entre threads) e como, em geral, coroutines sao mais eficientes que threads. A feature, porem, esta em estado bem experimental e nem tem uma JSR ainda e deve entrar na JVM com sorte apenas na versao 9.</div><div><br /></div><div><span class="Apple-style-span" ><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; background-color: rgb(255, 255, 255); ">Project Lambda: To Multicore and Beyond - </span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=50561&ts=1317708055751" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: none; ">Alex Buckley</a> e </span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=61920&ts=1317708055751" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: underline; ">Daniel Smith</a> da Oracle</span></span></div><div><span class="Apple-style-span" >Uma feature que deve vir na JDK8, lambdas sao uma forma mais simples do que closures - ou melhor, algo muito parecido. Para quem segue a lista de desenvolvimento de lambda, ha poucas novidades - mas uma delas meio bombastica: JDK8 trara (muito provavelmente) o que eles chamaram de <a href="http://www.google.com/url?sa=t&source=web&cd=2&ved=0CCYQFjAB&url=http%3A%2F%2Fwww.wiki.jvmlangsummit.com%2Fimages%2Fa%2Fa1%2F2011_Goetz_Extension_Slides.pdf&ei=qKGKTp-5N4b9sQKGpqndBA&usg=AFQjCNEQvso1_vSKG69l-aN8U_hIUCcOLg">virtual extension methods</a> - essencialmente trazendo as <a href="http://www.scala-lang.org/node/126">traits de scala</a> para java - como uma feature da JVM (e nao apenas do compiler, como eh o caso de scala). Nao sei quanto as pessoas se importam com isso, mas basicamente teremos uma forma limitada de heranca publica em java. Com essa feature, teremos adicao de varios metodos nas interfaces basicas de collections, permitindo manipulacao e iteracao das collections de forma paralela (usando o framework Fork-Join jah presente no JDK7).</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" ><span class="Apple-style-span" ><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; background-color: rgb(255, 255, 255); ">Why Doesn't Java Have Instant Turnaround? - </span></span><span class="Apple-style-span" style="font-family: Arial, Verdana, sans-serif; background-color: rgb(255, 255, 255); "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=37134&ts=1317708539489" style="font-family: Arial, Verdana, sans-serif; color: rgb(0, 85, 170); text-decoration: underline; ">Jevgeni Kabanov</a> da <a href="http://www.zeroturnaround.com/">Zero TurnAround</a></span></span></div><div><span class="Apple-style-span" >Quase uma propaganda do produto principal da empresa (o JRebel), mas uma boa palestra de qualquer maneira (alias que ainda nao peguei nenhuma palestra de baixa qualidade). JRebel promete que quase nunca sera necessario fazer o ciclo de build / redeploy cada vez que voce mudar algo na aplicacao. Na MAPS, temos usado com sucesso o Jetty rodando de dentro do Eclipse no projeto, com praticamente o mesmo efeito. No fim, o palestrante mencionou um <a href="http://www.zeroturnaround.com/liverebel/">novo produto da empresa</a>, dessa vez para diminuir o tempo de deployment de aplicacoes em producao - o que me deixou bem interessado.</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >JVM Bytecode for Dummies - Charles Oliver Nutter da EngineYard</span></div><div><span class="Apple-style-span" >Uma palestra bem tecnica de como gerar bytecode e como ele eh interpretado na JVM. Charles inclusive <a href="https://github.com/headius/bitescript">escreveu uma DSL (em ruby) para geracao de bytecode</a> e <a href="https://github.com/qmx/jitescript">mostrou uma biblioteca java parecida</a>. Fora isso, os exemplos foram dados usando <a href="http://asm.ow2.org/">ASM</a>. </span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Exibition Hall</span></div><div><span class="Apple-style-span" >Muitos dos expositores eram de empresas como a EngineYard: prestam servicos provendo plataforma de deployment e/ou facilitando deployment em ambientes de cloud. Claramente, o mundo java corporativo esta se movendo na direcao da nuvem - onde apropriado, claro.</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Amanha teremos mais um dia recheado de boas palestras.</span></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-51450850298676892692011-10-02T20:41:00.003-03:002011-10-02T22:05:18.722-03:00JavaOne 2011 Day 1<span class="Apple-style-span" >Este eh o primeiro de uma serie de reports sobre o que aconteceu no JavaOne 2011 (da minha perspectiva claro)</span><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Hoje o dia foi dedicado a inscricao e recolhimento de material. Para o JavaOne, soh teve atividades para quem assinou o <a href="http://www.oracle.com/javaone/program/schedule/university/index.html">Java University</a> - uma serie de cursos sobre Java. Eu achei muito basicos os cursos entao acabei nao assinando.</span></div><div><span class="Apple-style-span" >Mas como congressista do JavaOne tem acesso ao Oracle Open World, resolvi assistir algumas palestras (mas consegui entrar em apenas 3) e tentar conversar com alguns <a href="http://en.wikipedia.org/wiki/Java_User_Group">JUG</a> leaders.</span></div><div><br /></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; background-color: rgb(255, 255, 255); "><span class="Apple-style-span" >Key to Successful Implementations: Communication and Mandatory Education</span></span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" >Palestra ministrada por um <a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=15284&ts=1317600987560">consultor de Rotterdan</a> envolvido em implantacao de varios sistemas de <a href="http://en.wikipedia.org/wiki/Enterprise_resource_planning">ERP</a> na cidade, Gerard Stan prega que qualquer organizacao deve manter um programa obrigatorio de educacao dos seus funcionarios (com o slogan No Education, No Access) e mostrou <a href="http://www.oracle.com/us/products/applications/ebusiness/hrm/053815.html">uma ferramenta</a> para ajudar no gerenciamento de cursos e treinamento (mas acho que soh esta disponivel para quem eh cliente do Oracle E-Business Solution). Achei a ideia da palestra bem interessante, mas nada que ja nao estamos fazemos na MAPS.</span></div><div><span class="Apple-style-span" ><br /></span></div><div><span class="Apple-style-span" ><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">Highly Available Oracle Database: The Unknown Details</span></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; "><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; "><a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=19915&ts=1317601717159">Ministrada por uma Database Architect</a> da universidade de Utah, esta palestra mostrou varias praticas e ferramentas para se manter Alta Disponibilidade em um servidor de Banco de Dados. Esta palestra foi bem estranha - parecia muito com uma propaganda das funcionalidades de HA existentes no Oracle 11g/i. Mas algumas parecem interessantes (como o flashback, restore points manual ou automaticamente gerados) e algumas tecnicas tambem (como por exemplo, apenas ligar o SafeGuard e o FlashBack no servidor de backup para nao comprometer o servidor de producao).</span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; "><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; "><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span" >Managing Your Oracle Applications in Today's Economy: Ask the Experts</span></span></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; "><span class="Apple-style-span" style="font-size: 12px; background-color: rgb(255, 255, 255); "><br /></span></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; "><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span" >Mais um painel de discussao do que uma palestra propriamente dita, esta palestra (liderada por <a href="https://oracleus.wingateweb.com/scheduler/speakers/speaker.jsp?key=59777&ts=1317602249711">um funcionario da IBM</a>) falou muito sobre gerenciamento de dados e governanca de informacoes dos aplicativos da Oracle - mas acho que o conceito se aplica a qualquer software de grande porte que gera muitos dados. (por exemplo, o <a href="http://www.mapsrisk.com.br/produto/pegasus/">Pegasus</a>). </span></span></span><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; ">Os demais participantes do painel eram parceiros Oracle ou IBM que adotaram ou participaram da adocao das praticas de gerenciamento de informacoes discutidas. Sao elas:</span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; ">-clonar ou nao banco de dados de producao para desenvolvimento / testes de atualizacao: a discussao girou em torno da criacao de um banco 'dummy' com dados parecidos com a producao mas de menor tamanho ou ainda mascaramento dos dados sensiveis. Um dos palestrantes comentou que a <a href="http://www.google.com/url?sa=t&source=web&cd=1&ved=0CF0QFjAA&url=http%3A%2F%2Fwww.travelport.com%2F&ei=NQaJTu-VBYjWiAKH_bGoDA&usg=AFQjCNHFCAUhY3gGhazoiRXnkib5nRnkcg">TravelPort</a> conseguiu economizar quase 40% dos custos de storage do banco de dados (que usava a infra-estrutura da Oracle on-demand) usando bancos de dados dummy para desenvolvimento e testes ao inves de clones da producao.</span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; ">-arquivamento de dados "mortos": softwares e processos para arquivamento de dados para mitigar os prejuizos causados pelo crescimento excessivo de dados. Os palestrantes sugeriram a criacao de um grupo para gerenciamento de tais dados arquivados e mostrou algumas <a href="http://www-01.ibm.com/software/data/data-management/optim-solutions/">ferramentas da IBM para ajudar</a>. Este painel foi mais voltado para os clientes das aplicacoes de grande porte e menos para desenvolvedores (tanto eh que fui perguntado o que eu fazia ali).</span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; "><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, 'MS Sans Serif', Helvetica; font-size: medium; ">Agora esta tendo o keynote do Larry Ellion mas precisei voltar ao hotel e me preparar para amanha, quando as palestras tecnicas do JavaOne comecam.</span></div><div><span class="Apple-style-span" ><br /></span></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com2tag:blogger.com,1999:blog-956246568570408822.post-43478517168140161252011-06-18T15:10:00.004-03:002011-06-18T16:14:39.050-03:00Algumas ferramentas da JDKAlgumas pessoas veem me perguntar às vezes quais ferramentas usar para diagnosticar uma aplicação que não está se comportando como deveria. Na maioria das vezes é possível diagnosticar uma aplicação em execução apenas com as ferramentas que vem junto com a JDK mas que muitas pessoas desconhecem mas que (na minha opinião) todos deveríamos conhecer. A maioria das ferramentas abaixo está presente tanto na JDK5 quanto na JDK6 e a maioria delas precisa ser executada com o mesmo usuário que executa o processo. Por último, os comandos abaixo são da versão solaris da JDK e podem ter alguma diferença se executadas em outros sistemas operacionais.<div><br /></div><div><span class="Apple-style-span" ><b>JPS</b></span></div><div>Parecida com o <i>ps</i> dos UNIX'es, mas lista apenas os processos java em execução, mostrando o <i>pid (o process id) </i>e o nome da classe <i>main</i> que iniciou o processo. Com a opção '-v', mostra toda a linha de comando usada para iniciar o processo e com a opção '-l' mostra o nome completo da classe main.</div><div><div><br /></div><div><span class="Apple-style-span" ><b>JSTACK</b></span></div></div><div>Uma vez identificado o <i>pid</i> da aplicação, precisamo ver o que acontece com ela. O comando jstack <pid> mostra na tela um stacktrace de todas as threads da aplicação e verifica se há algum deadlock entre as threads. Além disso, é possível identificar se alguma thread está parada em algum ponto ou esperando por I/O.</pid></div><div><pid><br /></pid></div><div><span class="Apple-style-span" ><b>JINFO</b></span></div><div><i>jinfo <pid></pid></i> mostra todas as sytem properties e todas as flags da jvm.</div><div><br /></div><div><span class="Apple-style-span" ><b>JMAP</b></span></div><div><i>jmap <pid></pid></i> mostra todas as bibliotecas ligadas à sua aplicação, bem como o <i>offset</i> de memória em que estão mapeadas. Esta informação não é tão útil a menos que estejamos tentando identificar a causa de um crash da jvm. Normalmente usaremos <i>jmap -heap <pid></pid></i> para ver o estado da memória separado por região incluindo o <i>permgen</i>. Caso um problema de memória seja identificado, é possível gerar um histograma com os contadores de todos as instâncias dos objetos vivos com a flag <i>-histo</i> ou ainda gerar o heap dump com a flag <i>-dump:<dump options=""></dump></i>.</div><div><br /></div><div><b><span class="Apple-style-span" >JCONSOLE</span></b></div><div>Se tudo mais falhar, é possível tentar usar uma ferramenta gráfica chamada <i>jconsole</i> que se conecta à um processo java e consegue ver todas as informações anteriores e ainda inspecionar objetos expostos via JMX.</div><div><br /></div><div><pid>Como pudemos ver, é possível obter várias informações sobre uma aplicação em execução (e possivelmente diagnosticar problemas) apenas usando as ferramentas que vem junto com a JDK.</pid></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-28045563111823406322010-10-04T17:48:00.003-03:002010-10-06T12:05:43.787-03:00OutOfMemoryError explicadoA resposta para o <a href="http://mapsdev.blogspot.com/2010/09/outofmemoryerror.html">problema anterior</a> passa por duas explicações:<br /><br /><span style="font-weight: bold;font-size:180%;" >A pilha de execução</span><br />Todos os operadores na máquina virtual operam sobre elementos da pilha de execução. Isso significa que, por exemplo, a expressão abaixo:<br /><br /><pre class="brush: java;"><br />int x = 1 + 2;<br /></pre><br /><br />se torna algo como:<br /><pre><br />empilha 1; // a pilha agora contem 1<br />empilha 2; // a pilha agora contem 1, 2<br />soma; // os 2 elementos da pilha sao desempilhados e somados. A pilha contem 3<br />guarda em x; //o 3 eh desempilhado e guardado em x<br /></pre><br /><br />Parecido com assembly ASM.<br /><br /><span style="font-weight: bold;font-size:180%;" ><br />Variáveis locais</span><br />Variáveis locais (e argumentos de métodos) são guardados em uma "tabela" por índice, na ordem em que são declaradas em um método. Ou seja:<br /><br /><pre class="brush: java;"><br />public static void foo() {<br />int i = 0;<br />int j = 1;<br />}<br /></pre><br /><br />A variável 'i' ocupa o índice 0 da tabela de variáveis locais e a variável 'j' ocupa o índice 1. Se o método é não estático, a referência ao objeto (o 'this') ocupa o índice 0. Se o método possui argumentos, ele ocupa os índices subsequentes. Assim sendo:<br /><br /><br /><pre class="brush: java;"><br />public void foo(String arg0) {<br />int i = 0;<br />int j = 1;<br />}<br /></pre><br /><br />O 'this' ocupa o índice 0, o 'arg0' ocupa o índice 1 e assim por diante. Quando uma variável local sai de escopo, o compilador reutiliza o índice daquela variável para a próxima declaração de variável local. Em outras palavras, no código abaixo:<br /><br /><pre class="brush: java;"><br />public static void foo() {<br />{<br /> int i = 0;<br />}<br />int j = 0;<br />}<br /></pre><br /><br />a variável 'j' ocupa o índice '0' da tabela pois a variável 'i' saiu de escopo.<br /><br /><span style="font-weight: bold;font-size:180%;" >O problema</span><br />Sabendo disso, voltando ao problema original:<br /><br /><pre class="brush: java"><br /> public static void exec(int size) {<br /> {<br /> byte[] someData0 = new byte[size];<br /> process(someData);<br /> }<br /> //final do bloco<br /> byte[] someData1 = new byte[size]; // #<br /> process(someData); <br /> System.out.println("ok"); <br /> }<br /></pre><br /><br />Quando declaramos a segunda variável local 'someData1', o código a ser executado fica mais ou menos assim (em pseudo bytecode):<br /><br /><pre><br />empilha size; // a pilha contem size e o slot 1 contem o array antigo ainda<br />cria_array_bytes; // desempilha um inteiro e cria um array de bytes com o tamanho passado<br />guarda_em_1; // sobrescreve a variável local anterior<br /></pre><br /><br />Quando a instrução de criar um novo array de bytes é executado, a JVM lança uma exceção dizendo que não há mais espaço. Isso significa que o código, em bytecode, fica parecido com:<br /><br /><pre class="brush: java"><br /> public static void exec(int size) {<br /> <br /> byte[] someData0 = new byte[size]; // #1<br /> process(someData);<br /> <br /> //final do bloco<br /> someData0 = new byte[size]; // #2<br /> process(someData); <br /> System.out.println("ok"); <br /> }<br /></pre><br /><br />e o array criado em #1 só pode ser coletado depois que a instrução em #2 for executada - ou seja, tarde demais.<br />Isso explica também porque os outros exemplos funcionam corretamente. Na verdade, podemos perceber que basta declarar uma variável local qualquer entre as criações dos arrays para que o primeiro array seja coletado. De fato, o código abaixo funciona corretamente:<br /><br /><pre class="brush: java"><br /> public static void exec(int size) {<br /> {<br /> byte[] someData0 = new byte[size];<br /> process(someData);<br /> }<br /> int j = 0;<br /> //final do bloco<br /> byte[] someData1 = new byte[size]; // #<br /> process(someData); <br /> System.out.println("ok"); <br /> }<br /></pre><br /><br /><span style="font-weight: bold;font-size:180%;" >Conclusão</span><br />Não há nada de errado, tecnicamente, com o GC e nem com o código postado. Apenas (no bytecode) não estamos avisando que o primeiro array pode ser coletado, talvez isso devesse ser trabalho do compilador. Porém, na maioria dos casos, inserir uma instrução para anular as variáveis locais quando elas saem de escopo é desnecessário.<br /><span style="font-weight: bold;font-size:180%;" ><br /></span><span style="font-size:180%;"><span style="font-style: italic;font-size:100%;" >PS:</span></span><br />Estes artigos são meramente traduções/adaptações de um artigo que pode ser visto no <a href="http://www.javaspecialists.eu/">java specialists newsletter</a>. O artigo original e a resposta se encontram <a href="http://www.javaspecialists.eu/archive/Issue173.html">aqui</a> e <a href="http://www.javaspecialists.eu/archive/Issue174.html">aqui</a>.<br />A versão JIT-compiled da classe funciona normalmente devido a alguma otimização da JVM. Isso pode ser visto ao executar a classe com o modo 'compiled' ao invés do modo híbrido (o default) usando a flag -Xcomp.<br />Qualquer 'branching' (como um if ao invés do escopo vazio) vai fazer com que a JVM execute o código como esperado (sem a exceção), mesmo no modo interpretado.<br />Por último, alguns GC's mais espertos (como o G1) também são capazes de identificar o primeiro array como lixo e coletar corretamente.<div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-49730240954396047222010-09-24T14:58:00.016-03:002010-10-05T21:29:40.350-03:00OutOfMemoryError (??)Embora o título desse post possa parecer estranho, ele refere-se a um OutOfMemoryError que pode ocorrer em uma situação (bem específica é verdade), mas que aparentemente não deveria. Sem mais delongas, segue o código:<br /><br /><pre name="code" class="brush:java"><br />public class Foo {<br /><br /> public static void exec(int size) {<br /> {<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> }<br /> //final do bloco<br /> byte[] someData = new byte[size];<br /> process(someData); <br /> System.out.println("ok"); <br /> }<br /> <br /> private static void process(byte[] data) {<br /> } <br /><br /> public static void main(String[] args) { <br /> exec((int) (0.7 * Runtime.getRuntime().maxMemory())); <br /> } <br />} <br /></pre><br /><br />O código acima lança uma OutOfMemoryError: java heap space, muito embora não devesse, já que o objeto 'someData' sai de escopo após a linha 7, quando o bloco termina. A primeira impressão que pode ficar é, como as duas alocações estão próximas, não dá tempo para o GC limpar a memória. Tentaremos, então, chamar explicitamente o GC para ser executado no meio tempo:<br /><br /><br /><pre name="code" class="brush:java"><br />public class Foo {<br /><br />public static void exec(int size) {<br /> {<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> }<br /> //final do bloco<br /> System.gc();<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> System.out.println("ok");<br />}<br /><br />private static void process(byte[] data) {<br />}<br /><br /><br />public static void main(String[] args) {<br /> exec((int) (0.7 * Runtime.getRuntime().maxMemory()));<br />}<br />}<br /></pre><br /><br />Mesmo desse jeito, o código continua com o OutOfMemoryError. Algumas pessoas familiarizadas com o funcionamento do GC podem afirmar que chamar System.gc() <a href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#gc()">não necessariamente implica no GC ser executado de verdade</a>. Mas o código abaixo mostra(?) que, se formos insistentes, a memória é coletada apropriadamente:<br /><br /><br /><pre name="code" class="brush:java"><br />public class Foo {<br /><br /> public static void exec(int size) {<br /> {<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> }<br /> //final do bloco<br /> for(int i = 0; i < 10; i++) System.gc();<br /><br /> byte[] someData = new byte[size];<br /> process(someData); <br /> System.out.println("ok"); <br /> }<br /> <br /> private static void process(byte[] data) {<br /> } <br /><br /> public static void main(String[] args) { <br /> exec((int) (0.7 * Runtime.getRuntime().maxMemory())); <br /> } <br />} <br /></pre><br /><br />E também podemos ver que gerenciando "manualmente" a memória (ou seja, anulando a variável someData ao final do bloco), o código funciona normalmente:<br /><br /><br /><pre name="code" class="brush:java"><br />public class Foo {<br /><br />public static void exec(int size) {<br /> {<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> someData = null;<br /> }<br /> //final do bloco<br /> byte[] someData = new byte[size];<br /> process(someData);<br /> System.out.println("ok");<br />}<br /><br />private static void process(byte[] data) {<br />}<br /><br /><br />public static void main(String[] args) {<br /> exec((int) (0.7 * Runtime.getRuntime().maxMemory()));<br />}<br />}<br /></pre><br /><br />Por que será que se insistirmos, o problema some? Mais do que isso, há um problema com o gerenciamento de memória da VM? Devemos esquecer que o GC existe e gerenciar a coleta de objetos manualmente, anulando todas as variáveis quando elas deixam de ser usadas?<div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com3tag:blogger.com,1999:blog-956246568570408822.post-7289393799907867572009-10-06T16:42:00.026-03:002009-11-09T19:20:39.905-02:00Struts 2 com AnnotationsApesar de ser um assunto não muito atual, com bastante documentação, eu tive muito trabalho para escrever minha primeira aplicação com Struts 2. O <a href="http://struts.apache.org/2.1.6/index.html">site do projeto</a> tem muito conteúdo, mas nada mais prático para começar um projeto do zero. Em minha busca atrás de tutoriais, algo que me ajudasse, achei uma quantidade razoável de artigos/tutoriais, porém, nenhum que funcionasse efetivamente, principalmente utilizando annotations. Fiz o download de vários exemplos, uns funcionavam, outros não, mas não consegui fazer minha aplicação funcionar lendo apenas um tutorial. Dada essa dificuldade, pretendo colocar em prática o que eu aprendi, e, quem sabe, se algum desesperado precisar aprender uma aplicação simples utilizando Struts 2, esse tutorial funcione :-)<br /><br />Para começar, precisamos montar nosso ambiente, vamos precisar <a href="http://www.google.com.br/search?q=como+utilizar+o+tomcat+plugin+no+eclipse&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:pt-BR:official&client=firefox-a">do Eclipse, e do TomCat plugin.</a><br /><br />Nosso projeto ficará mais ou menos assim:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PuxHV_KQUGY4LPnfNNOUQwWMOTXFb6XA21uGz_J8Yh3btR1Qh929rTolmxFg_ix7uvV03ujGmqNbggg1NEG-ENpS3ghOTnuxPzJ7H0gE6qk-9N6YzdMArsxUdXxBULhcWXgN8C6uQvI/s1600-h/projeto_2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 265px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0PuxHV_KQUGY4LPnfNNOUQwWMOTXFb6XA21uGz_J8Yh3btR1Qh929rTolmxFg_ix7uvV03ujGmqNbggg1NEG-ENpS3ghOTnuxPzJ7H0gE6qk-9N6YzdMArsxUdXxBULhcWXgN8C6uQvI/s320/projeto_2.png" alt="" id="BLOGGER_PHOTO_ID_5394504362981319970" border="0" /></a><br /><br />Agora, criamos um projeto Java, e inserimos as bibliotecas do Struts 2 (essas são os jars necessários para o nosso exemplo simples, precisando de mais funcionalidades, vamos precisar de mais jars - a versão que estou utilizando é a 2.1.6)<br /><ul><li>commons-fileupload-1.1.1.jar</li><li>commons-logging-1.0.4.jar</li><li>freemaker-2.3.13.jar</li><li>ognl-2.6.11.jar</li><li>struts2-convention-plugin-2.1.6.jar (Esse jar é necessário somente se for utilizar annotations em sua aplicação, para as configurações em XML, esse jar não é necessário)</li><li>struts2-core-2.1.6.jar</li><li>xwork-2.1.2.jar</li></ul><br />Criamos uma pasta WEB-INF no nosso projeto, que vai conter nosso querido amigo web.xml (arquivo padrão para configuração do struts). Nele, precisamos obrigatoriamente configurar um FilterDispatcher, o default do struts é o org.apache.struts2.dispatcher.FilterDispatcher, mas nada impede o mapeamento de outros filtros.<br /><br /><br /><pre name="code" class="brush:xml"><br /><br /><?xml version="1.0" encoding="UTF-8"?><br /><web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xsi="http://www.w3.org/2001/XMLSchema-instance" schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><br /><br /> <filter><br /> <filter-name>struts2</filter-name><br /> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class><br /> </filter><br /><br /> <filter-mapping><br /> <filter-name>struts2</filter-name><br /> <url-pattern>/*</url-pattern><br /> </filter-mapping><br /><br /> <welcome-file-list><br /> <welcome-file>index.jsp</welcome-file><br /> </welcome-file-list><br /><br /></web-app><br /></pre><br /><br />Por que preciso de um <span style="font-style: italic;">FilterDispatcher</span>?! Bom, ele é o responsável por filtrar requisições vindas do browser! Junto com as Actions e os Interceptors, é a camada de Controller do MVC. MV O QUE?!<br /><br />MVC - Model-View-Controller, é o padrão implementado pelo Struts.<br /><br />Actions - Unidade mais básica do struts. É basicamente uma ação a ser executada pelo usuário.<br /><br />Interceptors - Uma das grandes novidades do Struts 2 com relação ao Struts 1, é o controle sobre o fluxo de execução de uma requisição, por meio de Interceptors. Com eles podemos executar métodos antes ou depois de uma determinada Action ser executada.<br /><br />Chega de teoria! Tendo o <span style="font-style: italic;">web.xml</span> configurado, é hora de cuidar da View! O Model não é nosso foco agora, porque ele seria o Domínio da nossa aplicação. Mas ... não temos domínio, é só um exemplo simples! Então vamos criar os jsp's necessários para o nosso exemplo.<br /><br />index.jsp (repare que esse é o jsp configurado no welcome-file do web.xml)<br /><br /><pre name="code" class="brush:xml"><br /><%@ page contentType="text/html; charset=UTF-8" %><br /><%@ taglib prefix="s" uri="/struts-tags" %><br /> <br /> <s:form action="helloworld" method="POST"><br /> <s:textfield name="requisicao" label="Digite algo"></s:textfield><br /> <s:submit></s:submit><br /> </s:form><br /></pre><br /><br />resposta.jsp<br /><br /><pre name="code" class="brush:xml"><br /><%@ page contentType="text/html; charset=UTF-8" %><br /><%@ taglib prefix="s" uri="/struts-tags" %><br /><br /> <s:property value="resposta"></s:property><br /></pre><br /><br />Ok, temos a View pronta. E agora? Agora é hora de criar as Actions! No Struts 2, não é necessário estender nenhuma classe, a Action pode ser um POJO simples, desde que devidamente anotada. Repare que o valor(value) da <span style="font-style: italic;">@Action</span> definida no método a executar, é o mesmo que colocamos na action do formulário no nosso jsp. Quando subirmos nossa aplicação, o Struts vai recuperar as classes anotadas, verificar quais são as actions (essa verificação é feita com o Struts procurando classes anotadas dentro do pacote <span style="font-style: italic;">action</span>), e é assim que o jsp vai saber que ação executar.<br /><br />Exemplo de Action (repare que é um POJO comum, anotado):<br /><pre name="code" class="brush:java"><br />package br.com.maps.action;<br /><br />import org.apache.struts2.convention.annotation.Action;<br />import org.apache.struts2.convention.annotation.Result;<br /><br />/**<br />* Action de exemplo para o tutorial de Struts 2 com annotation.<br />*<br />* @author finx<br />* @created Oct 19, 2009<br />*/<br />public class HelloWorldAction {<br /><br /> private String requisicao;<br /><br /> private String resposta;<br /><br /> /**<br /> * Executa a Action.<br /> *<br /> * @return resultado da execução da Action.<br /> */<br /> @Override<br /> @Action(value = "/helloworld", results = { @Result(name = "success", location = "/resposta.jsp"), @Result(name = "input", location = "/index.jsp") })<br /> public String execute() {<br /> this.resposta = "Olá! Eu estou executando uma ação do usuário, com a seguinte requisição: ";<br /> return "success";<br /> }<br /><br /> /**<br /> * Retorna a mensagem da requisição.<br /> *<br /> * @return a mensagem da requisição.<br /> */<br /> public String getRequisicao() {<br /> return requisicao;<br /> }<br /><br /> /**<br /> * Define a mensagem da requisição passada como parâmetro.<br /> *<br /> * @param requisicao a mensagem da requisição a ser definida.<br /> */<br /> public void setRequisicao(String requisicao) {<br /> this.requisicao = requisicao;<br /> }<br /><br /> /**<br /> * Retorna a resposta da requisição, chamada pelo componente <i>s:property</i> do jsp.<br /> *<br /> * @return a resposta da requisição, chamada pelo componente <i>s:property</i> do jsp.<br /> */<br /> public String getResposta() {<br /> return this.resposta + " [" + this.getRequisicao() + "].";<br /> }<br /><br />}<br /></pre><br /><br />Subindo nossa aplicação, ela deve ficar com essa cara:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMVqebX6ZlpeKJEmhdSqE0g9Ebv705_TW3ret-I56owZ7yZSIhpHBKKPUs8VmKjNV8v-Sy61ks2B0CSkQtwkRFYpRf8uOKw2PDWWl5utbqCXJwOIrw0qkttGqe3Ifw_fh0K3rXuMH7uLU/s1600-h/index_jsp_2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 148px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMVqebX6ZlpeKJEmhdSqE0g9Ebv705_TW3ret-I56owZ7yZSIhpHBKKPUs8VmKjNV8v-Sy61ks2B0CSkQtwkRFYpRf8uOKw2PDWWl5utbqCXJwOIrw0qkttGqe3Ifw_fh0K3rXuMH7uLU/s320/index_jsp_2.png" alt="" id="BLOGGER_PHOTO_ID_5394516304787645746" border="0" /></a><br /><br />Hmmm bem legal ... mas quando eu aperto o botão e não escrevo nada, a minha resposta é vazia! Há, aí é que entram os interceptadores. Estendendo nossa action de <span style="font-style: italic;">ActionSupport</span>, ganhamos um fluxo de execução com interceptadores configurado no arquivo <span style="font-style: italic;">struts-default.xml</span>, e aí é só configurar!<br /><br />Exemplo de requisição vazia:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLpY1CGRs-WUwxH4rVHIrkuhmW6i9-9wnSZZvj_oVet3N7jSLQccOAp0yjm9v7Vi_IsS9WJ69-60gZQoEmhu40x3HAdOaSYj3TsTeO-wnJ7L9GJpQIXCE-FFYRCIclB_k6EzjlBvuRIOI/s1600-h/resposta_jsp_com_erro_2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 95px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLpY1CGRs-WUwxH4rVHIrkuhmW6i9-9wnSZZvj_oVet3N7jSLQccOAp0yjm9v7Vi_IsS9WJ69-60gZQoEmhu40x3HAdOaSYj3TsTeO-wnJ7L9GJpQIXCE-FFYRCIclB_k6EzjlBvuRIOI/s320/resposta_jsp_com_erro_2.png" alt="" id="BLOGGER_PHOTO_ID_5394516634941671474" border="0" /></a><br /><br />Um exemplo de como a Action ficaria com validação:<br /><pre name="code" class="brush:java"><br />package br.com.maps.action;<br /><br />import org.apache.struts2.convention.annotation.Action;<br />import org.apache.struts2.convention.annotation.Result;<br /><br />import com.opensymphony.xwork2.ActionSupport;<br />import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;<br />import com.opensymphony.xwork2.validator.annotations.Validations;<br /><br />/**<br />* Action de exemplo para o tutorial de Struts 2 com annotation.<br />*<br />* @author finx<br />* @created Oct 19, 2009<br />*/<br />public class HelloWorldAction extends ActionSupport {<br /><br /> private String requisicao;<br /><br /> private String resposta;<br /><br /> /**<br /> * Executa a Action.<br /> *<br /> * @return resultado da execução da Action.<br /> */<br /> @Override<br /> @Action(value = "/helloworld", results = { @Result(name = "success", location = "/resposta.jsp"), @Result(name = "input", location = "/index.jsp") })<br /> @Validations(requiredStrings = @RequiredStringValidator(fieldName = "requisicao", message = "Campo obrigatório"))<br /> public String execute() {<br /> this.resposta = "Olá! Eu estou executando uma ação do usuário, com a seguinte requisição: ";<br /> return "success";<br /> }<br /><br /> /**<br /> * Retorna a mensagem da requisição.<br /> *<br /> * @return a mensagem da requisição.<br /> */<br /> public String getRequisicao() {<br /> return requisicao;<br /> }<br /><br /> /**<br /> * Define a mensagem da requisição passada como parâmetro.<br /> *<br /> * @param requisicao a mensagem da requisição a ser definida.<br /> */<br /> public void setRequisicao(String requisicao) {<br /> this.requisicao = requisicao;<br /> }<br /><br /> /**<br /> * Retorna a resposta da requisição, chamada pelo componente <i>s:property</i> do jsp.<br /> *<br /> * @return a resposta da requisição, chamada pelo componente <i>s:property</i> do jsp.<br /> */<br /> public String getResposta() {<br /> return this.resposta + " [" + this.getRequisicao() + "].";<br /> }<br /><br />}<br /></pre><br /><br />E um exemplo de como ficaria a nossa requisição vazia, com validação:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZRNOQF5kt26PTsBGc3ugPWu97espdbjdpeJG8ZLyybvlzARRK-A3ipZLfKCPriRaSMkYZxyr-tpu5XJx8jSll9YdAgFseEP3ZCVwgDqusb9t1uAWKvWdbV_RlwiQoPbNO0_znnM2zqWg/s1600-h/index_jsp_erro_2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 146px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZRNOQF5kt26PTsBGc3ugPWu97espdbjdpeJG8ZLyybvlzARRK-A3ipZLfKCPriRaSMkYZxyr-tpu5XJx8jSll9YdAgFseEP3ZCVwgDqusb9t1uAWKvWdbV_RlwiQoPbNO0_znnM2zqWg/s320/index_jsp_erro_2.png" alt="" id="BLOGGER_PHOTO_ID_5394517061000115890" border="0" /></a><br /><br />Finalmente, com o fluxo completo:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVgXpHnJLpZ7da-mcXNwA2apN9WS29KQvfyNOewKgj_YOC3lMmd3IlbhDC0zh8tLzHsvSgsdEqzzt-kK9QpI-BWZVIrHBPJPHxAO-HX4S2OjUCpHaNd0TS06n8CNL1QQHRHcjpkQQY8Cw/s1600-h/resposta_jsp_2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 98px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVgXpHnJLpZ7da-mcXNwA2apN9WS29KQvfyNOewKgj_YOC3lMmd3IlbhDC0zh8tLzHsvSgsdEqzzt-kK9QpI-BWZVIrHBPJPHxAO-HX4S2OjUCpHaNd0TS06n8CNL1QQHRHcjpkQQY8Cw/s320/resposta_jsp_2.png" alt="" id="BLOGGER_PHOTO_ID_5394517275159602786" border="0" /></a><br /><br />E, disponibilizando o exemplo utilizado nesse tutorial na <a href="http://mapsdev.googlecode.com/">página de projetos do blog</a>.<div class="blogger-post-footer">Dev@Maps</div>Finxhttp://www.blogger.com/profile/12240613423078475885noreply@blogger.com11tag:blogger.com,1999:blog-956246568570408822.post-55851715215890764612009-09-01T17:23:00.005-03:002009-09-07T11:45:14.826-03:00Just Java 2009Daqui a duas semanas (dias 15, 16 e 17 de setembro) ocorrerá a oitava edição do Just Java. O evento contará com a apresentação do trabalho <span style="font-style: italic;">"Performance com Hibernate em Cluster"</span> por membros de nossa equipe técnica. Estudaremos um <span style="font-style: italic;">"case"</span> de processamento distribuído de dados e os seguintes tópicos serão abordados:<br /><ul><li>Distribuição de tarefas por JMS</li><li>Hibernate<ul><li>Cuidados com FlushMode e gerenciamento do PersistenceContext</li><li>Lock otimista com uso de @Version</li><li>Uso de cache secundário</li></ul></li></ul> Esperamos vê-los no evento.<div class="blogger-post-footer">Dev@Maps</div>jrenauthttp://www.blogger.com/profile/16232874619067763399noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-67539926127422558212009-07-21T15:00:00.008-03:002009-09-22T15:39:00.058-03:00Java Generics - Parte I: DefiniçõesEmbora tenham sido introduzidos <a href="http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html">há quase cinco anos, com o lançamento do java 1.5 (codinome Tiger)</a>, os generics em java são fonte de confusão para muitas pessoas - mesmo programadores mais experientes. Esta série de posts tem como objetivo explicar como funcionam os generics em java, explicar seus diversos casos de uso e seus principais pontos de confusão. Este primeiro artigo é um pouco teórico mas artigos subsequentes se concentrarão na prática dos conceitos aqui explicados.<br /><span style="font-weight: bold;font-size:180%;">O que são generics</span><br />Generics é/são um recurso de linguagem que permite às classes especificarem uma parametrização "abstrata" de um tipo. Em outras palavras, os generics permitem que se escreva códigos que dependam de classes que serão definidas pelos clientes da sua classe. O exemplo óbvio são as coleções: quem escreveu a classe List, por exemplo, não poderia escrever uma variante para cada tipo de elemento que seria guardado dentro da List. Para poder definir de maneira uniforme a interface List (e sem que códigos clientes precisem fazer casts ou extender as classes), é possível escrever uma classe que tenha um parâmetro genérico, descrito na declaração da mesma. Em java, o parâmetro genérico é declarado dentro dos angle brackets '<' e '>':<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">public</span> <span style="font-style: italic;">interface</span> <span style="font-weight: bold;">List</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">E</span><span style="font-style: italic;">></span> {<br /><br /><span style="font-weight: bold;"> public</span> <span style="font-weight: bold;">E</span> get(<span style="font-weight: bold;">int</span> index);<br /><br /><span style="color: rgb(102, 51, 102);"> //resto da classe</span><br /><br />}<br /></code></pre><br />Permitindo escrever código cliente deste modo:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">ArrayList</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">String</span><span style="font-style: italic;">></span> listaDeStrings = new <span style="font-weight: bold;">ArrayList</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">String</span>>();<br /><br />listaDeStrings.add(<span style="color: rgb(153, 0, 0);">"umaString"</span>);<br /><br /><span style="font-weight: bold;">String</span> umaStrings = listaDeStrings.get(<span style="color: rgb(0, 0, 153);">0</span>);<br /></code></pre><br />Este recurso está presente em várias linguagens de programação, tal como <a href="http://www.cplusplus.com/doc/tutorial/templates/">C++</a>, <a href="http://msdn.microsoft.com/en-us/library/ms379564%28VS.80%29.aspx">C#</a>, <a href="http://www.haskell.org/haskellwiki/Parametric_polymorphism">Haskel</a>, <a href="http://www.scala-lang.org/node/113">scala</a>, etc, embora em algumas dessas linguagens seu nome seja diferente. Em <a href="http://en.wikipedia.org/wiki/Type_theory">teoria de tipos</a>, este recurso também é conhecido como <a href="http://en.wikipedia.org/wiki/Type_polymorphism">polimorfismo paramétrico</a>. Para as definições a seguir, onde está escrito "A instância de B" deve ser lida como "A é um substituto válido para B" em relação à tipagem.<br /><span style="font-size:180%;"><br /><span style="font-weight: bold;">Covariância, contravariância e invariância</span><br /></span><span style="font-size:100%;"><span style="font-size:100%;">Um pré-requisito para se entender as confusões mais comuns causadas por generics, é preciso entender um conceito conhecido como <a href="http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29">variância de tipos genéricos</a>:<br /></span><span style="font-weight: bold;"><br /></span></span><span style="font-size:100%;"><span style="font-weight: bold;"><span style="font-size:180%;">Covariância</span></span><br /></span>Por definição, diz-se que um tipo T com um parâmetro genérico B é covariante em B se e somente se toda instância de T[A0] é uma instância de T[A1] para toda classe concreta A0 que extende de uma outra classe concreta A1. Por exemplo em java (e em C#) arrays são covariantes, o que nos permite escrever:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">Object</span>[] arrayDeObjects = new <span style="font-weight: bold;">String</span>[10];<br /></code></pre>Considerando que o tipo do array é seu "parâmetro genérico", embora não use o generics explicitamente.<br /><br />Por outro lado, os generics "normais" em java não são covariantes, o que torna o código abaixo inválido:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="color: rgb(153, 51, 153);">//erro de compilação</span><br /><span style="font-weight: bold;">List</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">Object</span><span style="font-style: italic;">></span> listDeObjects = new <span style="font-weight: bold;">ArrayList</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">String</span><span style="font-style: italic;">></span>();<br /></code></pre>Um tipo genérico covariante não permite que se "escreva" nele - em outras palavras, um tipo genérico covariante é read-only, ou seja, o tipo genérico só pode aparecer em posições covariantes (apenas como parte de retorno de métodos). Para verificar porquê, imagine que o compilador permitisse o código abaixo:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">ArrayList</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">String</span><span style="font-style: italic;">></span> listDeStrings = <span style="font-weight: bold;">new</span> <span style="font-weight: bold;">ArrayList<string></string></span><span style="font-style: italic; font-weight: bold;"><</span><span style="font-weight: bold;">String</span><span style="font-style: italic;">></span>();<br /><br /><span style="color: rgb(153, 51, 153);">//a linha abaixo é reportada como erro pelo compilador</span><br /><span style="font-weight: bold;">ArrayList</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">Object</span><span style="font-style: italic;">></span> listDeObjects = listDeStrings;<br /><br /><span style="color: rgb(153, 51, 153);">//em um array list de objects, podemos inserir um Object</span><br />listDeObjects.add(<span style="font-weight: bold;">new</span> Object());<br /><br /></code></pre>A seguinte linha, porém, faria com que fosse lançada uma ClassCastException mesmo que ela não tenha nenhum cast:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">String</span> a = listDeStrings.get(<span style="color: rgb(0, 0, 153);">0</span>);<br /></code></pre>Os arrays em java resolvem (ou melhor, contornam) este problema lançando a exceção ArrayStoreException:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code>// array de strings<br /><span style="font-weight: bold;">String</span>[] arrayDeStrings = <span style="font-weight: bold;">new</span> <span style="font-weight: bold;">String</span>[<span style="color: rgb(0, 0, 153);">10</span>];<br /><br />//sem exceção, pois arrays são covariantes<br /><span style="font-weight: bold;">Object</span>[] arrayDeObjects = arrayDeStrings;<br /><br />// a linha abaixo, porém, lança a exceção ArrayStoreException<br />arrayDeObjects[<span style="color: rgb(0, 0, 153);">0</span>] = new Object();<br /><br /><br /></code></pre><br /><span style="font-size:180%;"><span style="font-weight: bold;">Contravariância</span></span><br />Por outro lado, um tipo genérico T é considerado contravariante em B se e somente se para qualquer classe concreta A0 super classe de A1, toda instância de T[A0] é uma instância de T[A1]. Embora isso pareça estranho a princípio, considere a interface Comparator:<br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">public </span><span style="font-style: italic;">interface</span> <span style="font-weight: bold;">Comparator</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">E</span><span style="font-style: italic;">></span> {<br /><br /><span style="font-weight: bold;">public</span> <span style="font-weight: bold;">int</span> compare(<span style="font-weight: bold;">E</span> arg0, <span style="font-weight: bold;">E</span> arg1);<br /><br />}<br /></code></pre><br />Sempre que um método precisar receber um Comparator para, por exemplo, String, poderia receber na verdade um Comparator para qualquer coisa que saiba comparar Strings - por exemplo, um Comparator de Objects.<br /><br />Desse modo, podemos ver que um tipo genérico contravariante é write-only, ou seja, o tipo paramétrico só pode aparecer em posições contravariantes (apenas como parte dos argumentos dos seus métodos).<br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Em JAVA</span></span><br />Como foi visto anteriormente, arrays em java são covariantes. Os tipos genéricos, porém, são invariantes nos tipos paramétricos nele definidos - ou seja, não são nem covariantes nem contravariantes. Isso permite que tipos genéricos sejam usados tanto em retorno de métodos quanto em seus argumentos. Na declaração de variáveis, porém, é possível especificar a variância de um tipo genérico através das palavras-chave extends (para covariância) e super (para contravariância).<br /><br />Assim sendo, uma List covariante em um tipo T tem o tipo:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">List</span><span style="font-style: italic;"><</span>? <span style="font-weight: bold;">extends</span> <span style="font-weight: bold;">T</span><span style="font-style: italic;">></span> listDeT = ....;<br /></code></pre><br /><br />A mesma sintaxe se extende para parâmetros de métodos, como neste método presente na interface Collection:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%; font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">public</span> <span style="font-weight: bold;">void</span> addAll(<span style="font-weight: bold;">Collection</span><span style="font-style: italic;"><</span>? <span style="font-weight: bold;">extends</span> <span style="font-weight: bold;">E</span><span style="font-style: italic;">></span> collection)<br /></code></pre><br /><br />Declarando um parâmetro dessa maneira, a collection é covariante em E, o que significa que no corpo do método, não podemos chamar métodos nessa lista que declarem E como parte do parâmetro.<br /><br /><br />Por outro lado, um Comparator contravariante em K tem o tipo:<br /><br /><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><span style="font-weight: bold;">Comparator</span><span style="font-style: italic;"><</span><span style="font-weight: bold;">? super</span> K<span style="font-style: italic;">></span> comparatorDeK = ....;<br /></code></pre><br /><br />As construções acima funcionam também para declaração de parâmetros de métodos e construtores, bem como o tipo de retorno de um método.<br /><br />Note a presença do wildcard '?'. O wildcard serve para indicar que o tipo exato da List e do Comparator é desconhecido, mas deve obedecer às restrições de variância impostas (respectivamente, covariante em T e contravariante em K). Como dito anteriormente, uma List covariante é "read-only"[1] (apenas é possível ler coisas da List) e, comparativamente, o Comparator contravariante é write-only. <a href="http://barrkel.blogspot.com/2006/07/covariance-and-contravariance-in-net.html">Este tipo de variância é chamado de use-site variance, contrastando com definition-site variance (presentes em, por exemplo, C# 4.0 e scala), onde a variância é indicada na própria declaração do tipo genérico.</a><br /><br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Conclusão</span></span><br /><br />Vimos aqui a definição de generics, bem como definições sobre variância e sobre como funciona a variância de arrays e demais tipos genéricos em Java. No próximo post, serão mostrados alguns usos de tipos variantes e os problemas mais comuns que aparecem com o uso de generics.<br /><br /><br /><br />[1] - não são read-only no sentido de que a List não pode ser modificada, mas sim no sentido que não se pode chamar métodos que usam o tipo genérico como parte do parâmetro de algum método.<div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com3tag:blogger.com,1999:blog-956246568570408822.post-75097195292271701682009-07-10T19:04:00.000-03:002009-07-10T22:47:24.782-03:00Scala parte I - sintaxeDurante a escrita de um outro artigo (ainda a ser publicado), percebi que preferia escrever os exemplos em uma linguagem de programação chamada Scala ao invés de Java. Por isso, ao invés de explicar todas as linhas do código, resolvi escrever um pouco sobre esta linguagem que, na minha humilde opinião, tem potencial para ser a próxima grande linguagem de programação.<div><br /></div><div><b><span style="font-size:180%;">O que é Scala?</span></b></div><div>Scala é uma linguagem de programação orientada a objetos, com tipagem estática e compilada, que é executada na JVM e na máquina virtual do .Net[1]. Além disso, Scala tem muitas funcionalidades típicas de linguagens de programação funcional, como closures, otimização de chamadas recursivas, etc. Por último, por ser primariamente executada na JVM, apresenta ótima compatibilidade com Java, podendo se aproveitar das muitas bibliotecas existentes. Foi inventada por Martin Odersky e seu nome se refere à escalabilidade da linguagem, na medida em que pode ser usada para escrever pequenos scripts ou grandes sistemas completos, sem que haja uma alteração na maneira de escrever.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:large;">Como usar</span></b></div><div>Todos os exemplos abaixo podem ser testados no console de Scala, invocado por scala ou scala.bat dependendo do seu sistema operacional.</div><div><br /></div><div><b><span class="Apple-style-span" style="font-size:large;">Um pouco sobre a sintaxe</span></b></div><div>Na sua estrutura geral, Scala se parece muito com Java, embora os detalhes da sintaxe sejam bastante diferentes. Para começar, a declaração de variável é precedida de val ou var e o tipo da variável é pós-escrito e separado do nome da variável por ':', desse modo:</div><div><br /></div><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><b>var</b> umaString: <b>String</b> = <span class="Apple-style-span" style="color: rgb(204, 0, 0);">"aaa"</span>;<br /><b>val</b> umNumero: <b>Int</b> = <span class="Apple-style-span" style="color: rgb(51, 102, 255);">1</span>;<br /></code></pre><div><br /></div><div>uma variável declarada como <span style="font-style: italic;">var</span> pode ser reassignada, enquanto que uma variável declarada com <span style="font-style: italic;">val</span> é imutável, ou seja, para todos os efeitos, equivalente a declarar uma variável '<span style="font-style: italic;">final</span>' em Java. O compilador de Scala permite, porém, que se omita o tipo de uma variável (que deve ser sempre inicializada durante a declaração):</div><div><br /></div><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><b>var</b> outraString = <span class="Apple-style-span" style="color: rgb(204, 0, 0);">"aaa"</span><br /><b>val</b> umDouble = <span class="Apple-style-span" style="color: rgb(51, 102, 255);">0.0</span><br /><br /></code></pre><div>E o ';' pode ser omitido se for desnecessário (ou seja, na última expressão de uma linha). </div><div>Métodos em Scala são definidos pela palavra chave '<span style="font-style: italic;">def</span>':</div><div><br /></div><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><b>def</b> metodoSemParametros():<b>String</b> = { <span class="Apple-style-span" style="color: rgb(204, 0, 0);">"a"</span> }<br /></code></pre><div><br /></div><div>O ':String' significa que o método devolve String. O retorno do método, se omitido, é o resultado da última expressão do método. Um método com parâmetros:</div><div><br /></div><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><b>def</b> metodoComUmParametroInteiro(<i>parametro</i>: <b>Int</b>) = <i>parametro</i> + <span class="Apple-style-span" style="color: rgb(51, 51, 255);">1</span><br /></code></pre><div><br /></div><div>Este método declara um parâmetro do tipo Int (que é o mesmo que 'int'). Neste caso, o compilador também infere e insere o tipo de retorno do método e os delimitadores também são opcionais para métodos compostos por apenas uma expressão. Por falar em expressão, Scala é composto quase que exclusivamente por expressões, o que significa que você pode atribuir quase qualquer coisa a uma variável (embora haja expressões do tipo <span style="font-style: italic;">Unit</span>, o equivalente a <span style="font-style: italic;">void</span> em C/C++/Java).</div><div><br /></div><div><br /><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><strong>val</strong> maior: <strong>String</strong> = { <strong>if</strong> (1 > 2) { "1 maior que 2"} <strong>else</strong> { "1 menor que 2"} }</code></pre></div><div><br /></div><div>Mesmo para expressões desse tipo, o compilador infere o tipo da expressão e o insere se este for omitido. As chaves também podem ser omitidas para expressões únicas:</div><div><br /></div><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><strong>val</strong> maior = <strong>if</strong> (1 > 2) <span style="color: rgb(204, 0, 0);">"1 maior que 2"</span> <strong>else</strong> <span style="color: rgb(204, 0, 0);">"1 menor que 2"</span></code></pre></div><div><br />Escrever classes em Scala é bem simples:<br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><br /><span style="font-weight: bold;">class</span> MinhaClasse {<br /><span style="font-weight: bold;">var</span> propriedadeMutavel: <span style="font-weight: bold;">String</span> = <span style="color: rgb(204, 0, 0);">"a"</span><br /><span style="font-weight: bold;">val</span> valorImutavel = <span style="color: rgb(51, 51, 255);">10</span><br />}<br /></code></pre></div><br /></div><br /><span style="font-style: italic;">Var</span> e <span style="font-style: italic;">Val</span> dentro do corpo da classe criam propriedades mutáveis e imutáveis respectivamente (o bytecode gerado é o equivalente a um campo e getters e setters).<br />Isso faz com que classes cliente não saibam se determinado valor vindo de outra classe é um campo ou uma invocação de método, uma propriedade conhecida como <a href="http://en.wikipedia.org/wiki/Uniform_access_principle">princípio de acesso a dados uniforme</a>.<br /><br />Em Scala, há o conceito de construtor primário que deve ser chamado pelos outros construtores e sua assinatura está junto com a declaracao da classe:<br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><br /><span style="font-weight: bold;">class</span> Ponto(x0: <span style="font-weight: bold;">Int</span>, y0: <span style="font-weight: bold;">Int</span>) {<br /><span style="font-weight: bold;">val</span> x = x0<br /><span style="font-weight: bold;">val</span> y = y0<br />}<br /></code></pre></div><br />Construtores auxiliares são declarados por métodos chamados 'this'<br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><br /><span style="font-weight: bold;">class</span> Ponto(x0: <span style="font-weight: bold;">Int</span>, y0:<span style="font-weight: bold;">Int</span>) {<br />val x = x0<br />val y = y0<br /><br /><span style="font-weight: bold;">def</span> this() = <span style="font-weight: bold;">this</span>(0, 0) //construtor vazio<br />}<br /></code></pre></div><br />Em especial, o construtor primário pode já ter a declaração de propriedades de classe:<br /><div><pre face="Andale Mono,Lucida Console,Monaco,fixed,monospace" size="12px" style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;"><code><span style="font-weight: bold;">class</span> Ponto(val x:<span style="font-weight: bold;">Int</span>, val y:<span style="font-weight: bold;">Int</span>) {<br /><span style="font-weight: bold;">def</span> this() = <span style="font-weight: bold;">this</span>(0, 0)<br />}<br /></code></pre></div><div><br />Métodos em Scala podem ter praticamente qualquer nome:<br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code><span style="font-weight: bold;">class</span> Ponto(val x:<span style="font-weight: bold;">Int</span>, val y:<span style="font-weight: bold;">Int</span>) {<br /><span style="font-weight: bold;">def</span> this() = <span style="font-weight: bold;">this</span>(0, 0)<br /><span style="font-weight: bold;">def</span> +(ponto: Ponto) = <span style="font-weight: bold;">new</span> Ponto(x + ponto.x, y + ponto.y)<br />}<br /></code></pre></div><br />Por último, generics em scala funcionam de maneira um pouco diferente e usam [ ] ao invés de < >, mas os detalhes serão dados em um post futuro. Além disso, posts posteriores vão mostrar construções avançadas, bem como algumas das propriedades que estão <a href="http://www.infoq.com/news/2009/07/scala-replace-java">tornando scala uma linguagem tão popular</a>. <br /></div><div><br /></div><div>[1] - Embora o suporte ao .Net esteja bem defasado e incompleto.<br /></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com0tag:blogger.com,1999:blog-956246568570408822.post-81459788809604378362009-06-23T12:41:00.001-03:002009-06-23T12:41:28.166-03:00JavaFX - conceitos básicos<span style="font-weight: bold;">Um pouco de background<br /><br /></span>O cenário para RIA's está bastante aquecido e <a href="http://javafx.com/">JavaFX</a> é a tecnologia desenvolvida pela Sun para disputar este mercado com <a href="http://www.adobe.com/br/products/flex/">Flash/Flex</a> e <a href="http://silverlight.net/">Silverlight</a>. Estas três tecnologias tem em comum o fato de serem disponibilizadas aos usuários através do browser porém executadas numa máquina virtual local. Desta forma é possível oferecer ao usuário interfaces muito mais elaboradas do que é possível com a combinação HTML+JavaScript (o cenário no qual trabalha <a href="http://www.google.com.br/url?sa=t&source=web&ct=res&cd=1&url=http%3A%2F%2Fjava.sun.com%2Fjavaee%2Fjavaserverfaces%2F&ei=w3w3SprUJ9yntgeHkOHeDA&usg=AFQjCNHClyI0BTzrydM9xT-ETzCKczKJ-A&sig2=sRD1Vh0QHHSr04VqBqTsTg">JSF</a> por exemplo).<br /><br /><span style="font-weight: bold;">A linguagem</span><br /><br />Um dos principais diferenciais em relação ao Java é o <span style="font-weight: bold;"><span class="Apple-style-span" style="font-style: italic;">estilo declarativo</span></span> de codificação. Por exemplo, compare a forma Java de se instanciar um objeto do tipo <span style="font-style: italic;">SomeObject</span> e sua dependência <span style="font-style: italic;">SomeObjectChild</span>:<pre><code>SomeObjectChild child = new SomeObjectChild();<br />child.setValue3(123);<br />SomeObject ref = new SomeObject();<br />ref.setValue1(123);<br />ref.setValue2("123");<br />ref.setChild(child);<br />ref.setSomeEventListener(new SomeEventListener() {<br />void someEvent() { <br /> //do something <br />}<br />});</code></pre><div>e a forma JavaFX de se instanciar um objeto equivalente:<pre><code>def ref : SomeObject = SomeObject {<br />value1: 123<br />value2: "123"<br />child: SomeObjectChild {<br /> value3: 123<br />}<br />someEvent: function(): Void {<br /> //do something<br />}<br />}</code></pre>O estilo declarativo é visivelmente mais claro e conciso.</div><div><br /><div>Outra recurso interessante é chamado de <span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-weight: bold;">binding</span></span>. Através deste recurso é possível amarrar um atributo a outro. Desta forma toda vez que algum atributo é modificado todos os que estiverem amarrados são notificados. Na verdade é mais do que uma notificação, a expressão com a qual foi feita a amarração é executada novamente atualizando assim o valor do atributo amarrado. Vejamos alguns exemplos: </div><pre><code>var stage : Stage;<br />var lbl: Label;<br /><br />lbl = Label {<br /> font : Font {<br /> size : 20<br /> }<br /> width: 100<br /><br /> translateX: bind (stage.scene.width - lbl.boundsInLocal.width) / 2<br /> translateY: bind (stage.scene.height - lbl.boundsInLocal.height) / 2<br /> text: bind<br /> if (stage.scene.width > 300) then<br /> "LARGE!"<br /> else<br /> "thin..."<br /><br /> textFill: bind<br /> if (stage.scene.width > 300) then<br /> Color.RED<br /> else<br /> Color.BLACK<br />};<br /><br />stage = Stage {<br /> title: "Simple Binding"<br /> width: 250<br /> height: 80<br /> scene: Scene {<br /> content: [lbl]<br /> }<br />}</code></pre>A variável <span class="Apple-style-span" style="font-style: italic;">stage </span>representa uma janela que será exibida para o usuário. Esta janela irá conter apenas um texto representado pela variável <span class="Apple-style-span" style="font-style: italic;">lbl</span>. Repare que os atributos do texto estão definidos usando a palavra-chave <span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-weight: bold;">bind</span></span>. Isto irá fazer com que toda vez que as propriedades <span class="Apple-style-span" style="font-style: italic;">stage.scene.width</span> e <span class="Apple-style-span" style="font-style: italic;">stage.scene.height</span> forem modificadas os atributos <span class="Apple-style-span" style="font-style: italic;">text</span>, <span class="Apple-style-span" style="font-style: italic;">textFill</span>, <span class="Apple-style-span" style="font-style: italic;">translateX </span>e <span class="Apple-style-span" style="font-style: italic;">translateY </span>sejam calculados novamente. Na prática isto fará com que o texto seja movido para o centro da janela sempre que ocorrer um redimensionamento da mesma e também irá mudar o texto sendo exibido e sua cor de acordo com a largura da janela. </div><div><br /></div><div>O recurso de <span class="Apple-style-span" style="font-style: italic;"><span class="Apple-style-span" style="font-weight: bold;">binding </span><span class="Apple-style-span" style="font-style: normal;">é bastante poderoso e permite manter o estado dos componentes da janela sincronizados em torno de atributos chaves sem que para isso seja necessário definir listeners de eventos como seria feito numa interface Swing tradicional. </span></span></div><div><br /></div><div>O exemplo acima não reflete isso mas este recurso facilita a construção da interface no padrão MVC. Fica bem simples sincronizar os componentes da <span class="Apple-style-span" style="font-style: italic;">View </span>que exibem dados aos atributos do <span class="Apple-style-span" style="font-style: italic;">Model </span>que armazenam estes dados. Desta forma ações (<span class="Apple-style-span" style="font-style: italic;">Controller</span>) que impactam o <span class="Apple-style-span" style="font-style: italic;">Model </span>irão automaticamente atualizar a <span class="Apple-style-span" style="font-style: italic;">View </span>sem que isto fico explícito no código das ações. Portanto é possível alcançar um menor acoplamento entre estas camadas ficando de fato possível alterar componentes da <span class="Apple-style-span" style="font-style: italic;">View</span> sem impactar as camadas de <span class="Apple-style-span" style="font-style: italic;">Model</span> e <span class="Apple-style-span" style="font-style: italic;">Controller</span>.<br /><br /><span style="font-weight: bold;">Mixins</span><br /><br />Até a versão 1.1 do JavaFX existia suporte a herança múltipla. Este recurso foi eliminado na versão 1.2 em favor de "mixins". Este recurso permite que interfaces tenham uma implementação padrão de um ou mais de seus métodos. Desta maneira, uma classe qualquer que deve implementar uma interface referencia o mixin da interface ao invés da própria interface. Vejamos um exemplo simples composto de duas interfaces, dois mixins, uma classe abstrata e uma concreta:<br /><br /><span style="font-style: italic;">Interfaces (Java)</span>:<br /><pre><code><br />public interface Persistable {<br /> void save();<br /> void delete();<br />}<br /><br />public interface Identifiable {<br /> String getIdentity();<br />}<br /></code></pre><br /><span style="font-style: italic;">Mixins (JavaFX)</span>:<br /><pre><code><br />public mixin class IdentifiableMixin extends Identifiable {<br /> public override function getIdentity() : String {<br /> return toString();<br /> }<br />}<br /><br />public mixin class PersistableMixin extends Persistable {<br /> public override function save() : Void {<br /> Persister.save(this);<br /> }<br /><br /> public override function delete() : Void {<br /> Persister.delete(this);<br /> }<br />}<br /></code></pre><br /><span style="font-style: italic;">Classe abstrata (Java)</span>:<br /><pre><code><br />public abstract class Entity {<br /> private Long id;<br /><br /> public Long getId() {<br /> return id;<br /> }<br /><br /> public void setId(Long id) {<br /> this.id = id;<br /> }<br />}<br /></code></pre><br /><span style="font-style: italic;">Classe concreta (JavaFX)</span>:<br /><pre><code><br />public class SomePersistableIdentifiableEntity extends Entity, PersistableMixin, IdentifiableMixin {<br /> public-init var field: String;<br /><br /> public override function toString() {<br /> return field;<br /> }<br />}<br /></code></pre><br />Desta maneira a classe <span style="font-style: italic;">SomePersistableIdentifiableEntity</span> implementa as interfaces <span style="font-style: italic;">Persistable</span> e <span style="font-style: italic;">Identifiable</span> sem no entanto ter sido obrigado a implementar os métodos da interface pois foram utilizados as definições providas pelos "mixins". Caso necessário é possível sobreescrever os métodos para modificar algum comportamento. Graças a este recurso não foi preciso <span style="font-style: italic;">"sujar"</span> a árvore de herança da classe com implementações dos métodos das interfaces. De uma maneira geral "mixins" promovem reuso de código e consistência nas chamadas a métodos de interfaces. Permitem que diversas classes que querem implementar determinada interface já ganhem de brinde uma implementação padrão de um ou mais de seus métodos.<br /><br />Num próximo post sobre JavaFX iremos falar sobre novos modificadores de acesso a variáveis, operadores especiais para trabalhar com listas e mais.<br /></div><div class="blogger-post-footer">Dev@Maps</div>jrenauthttp://www.blogger.com/profile/16232874619067763399noreply@blogger.com2tag:blogger.com,1999:blog-956246568570408822.post-26277697997885996712009-06-14T23:51:00.000-03:002009-06-16T11:32:49.353-03:00A JVM e seu compilador JITAté mesmo entre alguns programadores Java, há certas dúvidas sobre como alguns aspectos da JVM funcionam. Em particular, embora muitos saibam que existe um compilador durante a execução do programa, poucos sabem exatamente quais os benefícios. Mais do que isso, não é raro encontrar desenvolvedores procurando um compilador <i>ahead of time</i> (AOT) para java para gerar programas nativos. Este post pretende mostrar algumas vantagens do compilador <i>just in time</i> (JIT), bem como demonstrar um pouco da sua capacidade. As informações contidas neste artigo se referem ao Hotspot, o compilador jit da Sun. Porém, a maior parte da informações contida é aplicável a todas as JVM's.<div><br /></div><div style="font-weight: bold;"><span style="font-size:130%;">Hotspot client e server</span></div><div>Antes de falar especificamente sobre o Hotspot, é preciso saber que existem na verdade dois Hotspot's, chamados de client e server. </div><div>O client compiler é o compilador presente na JRE de 32 bits. Ele tem como objetivos gerar código nativo rapidamente e, preferencialmente, sem afetar a responsividade do código sendo executado. Seu nome vem do fato de que é preferivelmente utilizado em aplicações clientes que normalmente interagem com usuários. Já o server compiler está presente apenas no JDK (e nas JRE de 64bits) e exige mais tempo para gerar código nativo. Contudo, várias otimizações <a href="http://mapsdev.blogspot.com/2009/05/java6u14-ea-e-le.html">só estão presentes no server compiler</a>. Seu principal uso é para aplicações que tipicamente executam em servidores, com um tempo de vida maior. Para ativar o server, basta invocar o executável java com a opção -server.</div><div><br /></div><div style="font-weight: bold;"><span style="font-size:130%;">E como funciona o Hotspot?</span></div><div>O Hotspot (nome do compilador <i>jit</i> da máquina virtual da Sun) observa a execução dos programas e, a partir do perfil de execução e da plataforma em que se encontra, gera código nativo para o programa sendo executado. Isso significa que ele pode (e o faz) gerar código específico para o processador em que o programa está sendo executado, se aproveitando de registradores específicos e instruções especiais. </div><div><br /><span style="font-size:130%;"><span style="font-weight: bold;">Exemplo prático</span></span><br />Para ilustrar o comportamento do JIT, vamos mostrar um pequeno exemplo. O código abaixo (que também se encontra no <a href="http://code.google.com/p/mapsdev/">repositório de códigos deste blog</a>) é bem simples e mostra bem o que o Hotspot é capaz de fazer:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">long</span> bits = 0L;<br /><span style="font-weight: bold; color: rgb(51, 51, 255);">if</span>(args.length > <span style="color: rgb(153, 0, 0);">0</span>) {<br />bits = <span style="font-weight: bold;">Long</span>.<span style="font-style: italic;">parseLong</span>(args[<span style="color: rgb(153, 0, 0);">0</span>]);<br />}<br /><span style="font-weight: bold;">long</span> start = <span style="font-weight: bold;">System</span>.<span style="font-style: italic;">nanoTime</span>();<br /><span style="font-weight: bold;">int</span> n = <span style="color: rgb(153, 0, 0);">2000000001</span>;<br /><span style="font-weight: bold;">boolean</span> shift = bits > <span style="color: rgb(153, 0, 0);">0</span>;<br /><span style="font-weight: bold; color: rgb(51, 51, 255);">while</span> (n > <span style="color: rgb(153, 0, 0);">0</span>) {<br /><span style="font-weight: bold; color: rgb(51, 51, 255);"> if</span>(shift) {<br /> bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />}<br />n--;<br />}<br /><span style="font-weight: bold;">System</span>.<span style="font-style: italic;">out</span>.println("bits: "+ bits);<br /><span style="font-weight: bold;">long</span> end = <span style="font-weight: bold;">System</span>.<span style="font-style: italic;">nanoTime</span>();<br /><span style="font-weight: bold;">System</span>.<span style="font-style: italic;">out</span>.println(<span style="font-weight: bold;">TimeUnit</span>.<span style="font-style: italic;">NANOSECONDS</span>.toMillis(end-start) + "ms");<br /></code></pre><br />Executando o código acima nos três modos (puramente interpretado, compilado com o client compiler e com o server compiler) passando o número 1 como argumento, temos os seguintes resultados (em um Solaris usando java6u14):<br /><blockquote><br /><span style="font-size:85%;"><span style="font-family:courier new;">Interpretado (invocado com -Xint): infinito!</span><br /><span style="font-family:courier new;">Client compiler: 2903ms</span><br /><span style="font-family:courier new;">Server compiler: 11ms</span></span></blockquote><br />O resultado do server compiler é impressionante. Para comparar, o código C equivalente (compilado no GCC 3.4.6), no mesmo computador mas com o tempo medido com o utilitário 'time' do UNIX:<br /><br /><blockquote><span style="font-size:85%;"><span style="font-family:courier new;">gcc: 7422ms</span><br /><span style="font-family:courier new;">gcc -O1: 2541ms</span><br /><span style="font-family:courier new;">gcc -O5: 1447ms</span><br /></span></blockquote><br />A versão server é inclusive muito mais rápida que a versão nativa compilada com -O5 (o 5o nível de otimização do GCC - mais do que isso não trouxe melhorias para este exemplo). Mas mesmo a versão client tem desempenho parecido com o GCC -O1.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Java mais rápido que código nativo?</span></span><br /></div><div>Para entender o que ocorreu com o programa anterior, serão explicadas algumas das técnicas de otimização feitas pelo Hotspot. Para começar, o Hotspot detecta que é necessário otimizar o corpo do loop. Para isso, ele aplica uma técnica conhecida como <a href="http://en.wikipedia.org/wiki/Loop_unwinding">loop unrolling</a> com fator de 2. O loop resultante fica parecido com:<br /><br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">if</span>(n % 2 == 1) {<br /><span style="font-weight: bold;">if</span>(shift) bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />n--;<br />}<br /><span style="font-weight: bold;">while</span> (n > <span style="color: rgb(153, 0, 0);">0</span>) {<br /><span style="font-weight: bold;">if</span>(shift) {<br /> bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />}<br />n--;<br /></code><code> <span style="font-weight: bold;">if</span>(shift) {<br /> bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />}<br />n--;</code><br /><code> }<br /></code></pre></div><br />Porém, dentro do loop, o valor de shift não é alterado e o 'n--' não tem efeito sobre a computação sendo feita. O compilador, dessa vez, reordena as instruções para ficar parecido com:<br /><br /><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">while</span> (n > <span style="color: rgb(153, 0, 0);">0</span>) {<br /><span style="font-weight: bold;">if</span>(shift) {<br /> bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br /> bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />}<br />n--;<br />n--;<br />}<br /></code></pre></div><br />Para que a variável 'bits' não seja carregada mais de uma vez e porque a operação XOR (^) é associativa, o compilador resolve colapsar as duas instruções em uma só:<br /><br /><div><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><br /><span style="font-weight: bold;">while</span> (n > 0) {<br /><span style="font-weight: bold;"> if</span>(shift) {<br /> bits ^= (1 <span style="font-weight: bold;"><<</span> 5) ^ (1 <span style="font-weight: bold;"><<</span> 5);<br />}<br />n -= 2;<br />}<br /><br /></code></pre><br /></div>Nesse momento, o Hotspot percebe que a expressão:<br />(<span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>) ^ (<span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>)<br />na verdade é a constante 0! Assim, a parte interna do loop pode ser eliminada, bastando adicionar as instruções do seu efeito colateral (decrementar o n até 0). Dessa forma, o código final executado é parecido com:<br /><br /><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); line-height: 14px; width: 100%;font-family:Andale Mono,Lucida Console,Monaco,fixed,monospace;font-size:12px;"><code><span style="font-weight: bold;">if</span>(n % 2 == 1) {<br /><span style="font-weight: bold;">if</span>(shift) bits ^= <span style="color: rgb(153, 0, 0);">1</span> << <span style="color: rgb(153, 0, 0);">5</span>;<br />n--;<br />}<br />n = 0;<br /></code></pre><br /></div>É claro que esta é uma simplificação do que acontece realmente (o loop na verdade é dividido em três seções, mas estas explicações detalhadas ficam para outro post). A versão client compiler pára antes de fazer todas as otimizações para que o código nativo possa ser executado mais rapidamente. O código gerado, porém, não é o mais otimizado possível - que é um quase noop.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Conclusão</span></span><br />Não se preocupe em escrever o código java mais otimizado possível. É preferível escrever um código mais legível e deixar as otimizações mais estranhas para o Hotspot.<br />Embora não se possa afirmar que a JVM consiga gerar código tão eficiente quanto os compiladores nativos, é seguro afirmar, pelo menos, que eles tem desempenhos equivalentes.<br /><br /><span style="font-weight: bold;">PS:</span> O exemplo aqui presente e muitas outras discussões bastante interessantes podem ser acompanhadas no <a href="http://groups.google.com/group/jvm-languages">google groups de linguagens da jvm</a>.<br /><div><br /></div><div><span style="font-weight: bold;">update:</span> muitos erros de português...<br /><br /><span style="font-weight: bold;">update2:</span> Os tempos da versão java medidos com o time foram omitidos por serem virtualmente identicos ao tempo acima. Em todo caso, o user time é, em média, 100ms superior ao tempo medido de dentro da aplicação.<br /></div><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com5tag:blogger.com,1999:blog-956246568570408822.post-40082774635909414312009-05-30T20:59:00.002-03:002009-09-22T17:41:11.977-03:00Java6u14: EA e LESem fazer nenhum alarde (e uma semana antes do JavaOne 2009) a Sun resolveu lançar mais uma atualização para o JRE6 - o Update 14. Devido às indefinições sobre o Java7 (que ainda não possui uma JSR), a Sun tem feito, em suas atualizações do Java6, grandes modificações, entre as quais o <a href="http://java.sun.com/javase/6/webnotes/family-clsid.html">"novo plugin"</a> <a href="http://java.sun.com/javase/6/webnotes/6u10.html">no update 10</a>, capacidade de atualização "in place" para windows no <a href="http://java.sun.com/javase/6/webnotes/6u11.html">update 11</a>, o plugin de 64 bits no <a href="http://java.sun.com/javase/6/webnotes/6u12.html">update 12</a> e - o principal assunto deste artigo - análise de escape e o novo garbage collector (G1) no <a href="http://java.sun.com/javase/6/webnotes/6u12.html">update 14</a>.<div><br /></div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">Escape Analysis</span></div><div>A análise de escape permite à JVM detectar quando um objeto é "não escapante" (ou seja, seu ciclo de vida está confinado a um escopo local). Quando um objeto desse tipo é detectado, o JIT vai (supostamente) alocá-lo na pilha (ao invés do heap) e tratar seus campos como variáveis locais e, no melhor caso, trabalhar apenas com os registradores do seu CPU. Além disso, é garantidamente seguro ignorar os monitores destes objetos - uma otimização conhecida como "lock elision".</div><div><span class="Apple-style-span" style="font-weight: bold;"><br /></span></div><div><span class="Apple-style-span" style="font-weight: bold;">Um pouco de história:</span></div><div>Na época do desenvolvimento do Java6, a análise de escape estava prometida como um dos responsáveis por um aumento de performance sobre o Java5. Algumas JVMs da época já tinham essa <span class="Apple-style-span" style="font-style: italic;">feature </span>(ou pelo menos em teoria, de acordo com este <a href="http://www.research.ibm.com/people/g/gupta/escape.ps">artigo</a>), mas devido ao tempo escasso, a JVM6 era capaz de fazer a análise, mas <a href="http://www.infoq.com/articles/java-threading-optimizations-p1">não implementava nenhuma otimização </a><a href="http://blog.xebia.com/2007/12/21/did-escape-analysis-escape-from-java-6/">com essas informações.</a> </div><div><span class="Apple-style-span" style="font-weight: bold;"><br /></span></div><div><span class="Apple-style-span" style="font-weight: bold;">Na prática...</span></div><div>Vamos ver como a EA (escape analysis) e LE (lock elision) se saem em alguns microbenchmarks simples.</div><div>O primeiro teste consiste em alocar um objeto simples, com dois campos, dentro de um for, alterar o valor dos seus campos, e somá-los. Estas operações são feitas através de métodos ao inves de acessar os campos diretamente, com a análise de escape desligada primeiro, depois ligada.<br /></div><div>Antes de mais nada, a EA só pode ser ativada na jvm server (ou seja, está presente apenas na JDK6U14 e não na JRE6U14) e com uma opção não padrão (daquelas que começam com -XX)</div><div>-XX:+DoEscapeAnalysis</div><div><br /></div><div>A parte principal do código:</div><div><br /></div><div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code><br />public void execute() {<br />for (int i = 0; i < max; i++) {<br /> Foo foo = new Foo();<br /> foo.setNumA(i);<br /> foo.setNumB(i * i);<br /> total += foo.sum();<br />}<br />}<br /><br /></code></pre><br /></div><div><br /></div><div>Os resultados foram:</div><div><br /></div><div>Tempo de execução para 1000000000 iterações</div><div>client vm: 11922 ms</div><div>server vm: 8452 ms</div><div>server vm + EA: 1611ms</div><div><br /></div><div>Ou, em iterações por millisegundo:</div><div><div>client vm: 83872</div><div>server vm: 118306</div><div>server vm + EA: 620578</div></div><div><br /></div><div>Como pode ser visto, usando a EA, o pequeno teste ficou mais de 6x mais rápido. Claro que estes números não devem ser lidos literalmente, pois este teste foi especificamente designado para tirar vantagem da análise - em outras palavras não espere esta melhoria no eclipse do dia-a-dia ou no jboss em produção.<br /></div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">Lock elision</span></div><div>Lock elision é uma das técnicas que poderia ser uma gigantesca vantagem das linguagens dinamicamente compiladas sobre as estaticamente compiladas. E o update 14 especificamente menciona que com a análise de escape ativada, os locks também seriam eliminados. Executando o mesmo teste, agora com todos os métodos marcados como sincronizados, temos:</div><div><br /></div><div>Alterando o código anterior para:</div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code><br />public void execute() {<br /> for (int i = 0; i < max; i++) {<br /> SFoo foo = new SFoo();<br /> foo.setNumA(i);<br /> foo.setNumB(i * i);<br /> total += foo.sum();<br /> }<br />}<br /><br /></code></pre><div>Onde SFoo é idêntico a Foo, porém com seus métodos marcados como <span class="Apple-style-span" style="font-style: italic;">synchronized.</span></div><div><br /></div><div>Tempo de execução para 100000000 (perceba que eu tive que usar 10x menos operações para a versão sincronizada):</div><div><div>client vm: 6337 ms<br /></div><div>server vm: 4184 ms</div><div>server vm + EA: 276 ms (!!!)</div><div><br /></div><div>Ou, em iterações por millisegundo:</div><div><div>client vm: 15778</div><div>server vm: 23897</div><div>server vm + EA: 361271<br /></div><div><br /></div><div>Ou seja, o speedup aqui foi de 21x - bem melhor do que a versão não sincronizada. Este resultado sugere que o lock elision é, de alguma forma feito. Porém, se compararmos somente os resultados da EA, a versão sincronizada é quase 2x mais lenta, o que sugere que a JIT não elimina todo o overhead da entrada e saída do monitor - quem sabe para continuar com algumas garantias de visibilidade.<br /></div><div><br /></div><div>Já se alterarmos o código inicial para:</div><div><br /></div><pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"><code>public void execute() {<br /> for (int i = 0; i < max; i++) {<br /> Foo foo = new Foo();<br /> synchronized (foo) {<br /> foo.setNumA(i);<br /> foo.setNumB(i * i);<br /> total += foo.sum();<br /> }<br /> }<br />}<br /><br /></code></pre><div>Seria esperado que os resultados fossem parecidos com o primeiro caso, já que o monitor do objeto foo só é adquirido uma vez por iteração. Vamos aos resultados (dessa vez apenas com o EA ativado), desta vez combinado com outras opções presentes antes do update 14 que poderiam afetar este teste:</div><div><br /></div><div>Tempo em millisegundos para 1000000000 iterações: </div><div>server + EA: 9606ms</div><div>server + EA + Eliminate locks: 9543ms</div><div>server + EA + Biased locking: 9599ms</div><div>server + todas acima: 9515ms</div><div><br /></div><div>As opções acima (Eliminate Locks e Biased Locking) são ativadas respectivamente por: -XX:+EliminateLocks e -XX:+UseBiasedLocking e, supostamente, são ativadas por padrão.<br /></div><div>Aparentemente, um bloco sincronizado maior limita as otimizações que podem ser feitas pela análise de escape - os resultados obtidos estão aproximadamente 3x piores do que o teste anterior (com os métodos marcados com 'synchronized').<br /></div><div><br /></div><div>G1 e "Compressed OOPTS"</div><div>Além da EA, o update 14 trouxe também um novo garbage collector chamado G1 (garbage first), apresentado no <a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&yr=2008&track=javase">JavaOne 2008</a> e ainda em estágio experimental. Trata-se de um GC paralelo e que tenta garantir uma pausa máxima (que pode ser definida pela linha de comando) e pode ser ativada pela combinação de opções:</div><div><span class="Apple-style-span" style=";font-family:Arial;font-size:100%;" ><pre style="font-family: Monaco,Courier,'Courier New',monospace; color: rgb(68, 68, 68);">-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC</pre></span></div><div>Por último, os "compressed object pointers" também foram integrados. Quem usa uma jvm de 64bits já deve ter notado que o consumo de memória é bem maior do que na jvm de 32 bits. Isso ocorre porque as referências para objetos ocupam 64 bits, mesmo quando todo o espaço de endereçamento não é necessário. Com esta opção nas JVM de 64 bits, as referências para objetos continuam com 32 bits a menos que seja necessário. Esta opção é ativada por:<br /><span style="font-style: italic;font-size:100%;" ><br />-XX:+UseCompressedOops </span><br /><br />e já existia nas <a href="http://java.sun.com/javase/technologies/performance.jsp">JVM de "performance"</a>.</div><div><br /></div><div><br /></div><div>Mais informações sobre o G1 podem ser encontradas em:</div><div><a href="http://www.infoq.com/news/2008/05/g1">http://www.infoq.com/news/2008/05/g1</a><br /></div><div><a href="http://java.sun.com/javaone/sf/2008/articles/rockstar_tonyprintezis.jsp">http://java.sun.com/javaone/sf/2008/articles/rockstar_tonyprintezis.jsp</a><br /></div><div><br /></div><div>e uma pequena demonstração dos ponteiros comprimidos pode ser vista em:</div><div><a href="http://blog.juma.me.uk/2008/10/14/32-bit-or-64-bit-jvm-how-about-a-hybrid/">http://blog.juma.me.uk/2008/10/14/32-bit-or-64-bit-jvm-how-about-a-hybrid/</a><br /></div><div>(ainda na jvm6 de performance)</div><div><br /></div><div><span class="Apple-style-span" style="font-weight: bold;">Conclusão</span></div><div>Estas últimas atualizações podem trazer ganhos de performance muito bons para alguns cenários, embora haja alguma limitação no que a JVM pode fazer na presença de locks - o que pode muito bem ser corrigido em updates futuros ou quem sabe no jdk7. Embora eu espere que o JDK7 não demore a sair, acho muito interessante que a Sun não esteja se contendo em aperfeiçoar a sua JVM mesmo nas atualizações menores.</div><div><br /></div><div><br /></div><div><br /></div></div></div><div><br /></div><div><br /></div><br /><pre class="brush: java" ><br />public static void main(String[] args) {<br /> //yey<br /> /**<br /> * woot<br /> */<br />}<br /></pre><div class="blogger-post-footer">Dev@Maps</div>takeshihttp://www.blogger.com/profile/17859223226405878573noreply@blogger.com1tag:blogger.com,1999:blog-956246568570408822.post-49952391654747937632009-05-26T20:06:00.000-03:002009-06-08T13:58:07.338-03:00Falando em JavaOlá,<br /><br />sejam bem vindos ao Blog da Maps. Este primeiro post irá falar do evento "Falando em Java" organizado pela Caelum neste último domingo 24 de maio de 2009.<br /><br /> Este ano os palestrantes internacionais convidados foram Jim Webber da Thoughtworks e Bill Burke da Red Hat. Este último no entanto não conseguiu ir ao evento por problemas com seu visto para o Brasil. Sua palestra foi substituida por uma palestra adicional de Jim Webber. Seguem minhas impressões:<br /><br /><b>"Keynote: Guerrilha SOA" por Jim Webber</b><br /><br /> Boa apresentação. O palestrante demonstrou um ótimo preparo e muito conhecimento sobre o tema discutido. Jim contou rapidamente como a computação vem encarando o problema da integração entre softwares para então criticar o modelo atual. Segundo ele, este modelo não escala muito bem ou não se adequa muito bem por depender de middlewares que realizem a comunicação. O modelo que ele propõe faz uso da própria Web como middleware através de operações REST. REST propõe que funcionalidades da aplicação sejam abstraídas em "recursos" únicos (por exemplo uma URI) e que o acesso a estes recursos seja feito por meio de uma interface padronizada (por exemplo HTTP) e que desta forma sejam transportados representações destes recursos (html, json, xml, etc). Jim defende que a própria Web atende todos estes requisitos além de prover "methods" (GET, POST, PUT, DELETE) que ajudam a identificar as operações (ou serviços) que queremos executar. Neste modelo não é necessário nenhum tipo de middleware para realizar a comunicação entre aplicações, apenas a capacidade de disparar um request com determinado método para determinada URI e a capacidade de entender a resposta. Para quem quiser saber mais sobre isso segue o link da wiki: <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer" target="_blank">http://en.wikipedia.org/wiki/<wbr>Representational_State_<wbr>Transfer</a> .<br /><br /><b>"O profissional Java efetivo" por Paulo Silveira e Rafael Cosentino</b><br /><br /> Apresentação inconsistente. O tema parecia muito interessante porém a palestra foi mal conduzida. Os palestrantes não demonstraram preparo. Adotaram um modelo de apresentação baseado em piadas (internas, sem a menor graça) e perderam muito tempo com isso. Abstraindo a questão das piadas, os palestrantes se concentraram um demonstrar diversos problemas de integração entre softwares e qual era a maneira mais adequada de resolver cada um dados os requisitos da comunicação a ser estabelecida. Por exemplo, para uma integração semanal entre assistências técnicas e uma matriz sugeriram CSV pela simplicidade. Para um médico controlar remotamente um robô que está realizando uma operação em tempo real sugeriram um protocolo binário pela performance. Para "mashup's" (<a href="http://en.wikipedia.org/wiki/Mashup_%28web_application_hybrid%29" target="_blank">http://en.wikipedia.org/wiki/<wbr>Mashup_(web_application_<wbr>hybrid)</a>) foram sugeridos web services. Por terem se concentrado nas piadas acabaram não aprofundando nenhum dos exemplos apenas listando os prós e contras de cada solução adotada. Foi apenas no final da palestra que o Paulo conseguiu fazer alguns comentários alinhados com o título da palestra. Ele sugeriu (com razão) que profissionais Java devem continuar estudando sobre programação em geral, se envolver com a comunidade, ler blogs técnicos, etc. Concordo plenamente, inclusive a recomendação é válida para qualquer tipo de profissional. Hoje em dia as coisas mudam de figura muito rápido, o que hoje está em alta rapidamente pode estar em baixa. Para não ficarmos para trás temos que nos manter atualizados.<br /><br /><b>"JBoss Seam e WebBeans" por Alessandro Lazarotti e Ricardo Nakamura</b><br /><br /> Apresentação regular. Começaram com uma metáfora para explicar inversão de controle / injeção de dependências. Embora a metáfora tenha sido boa (um contraste entre ir até a padaria comprar o pão e receber o pão em casa) acabaram perdendo tempo com demasiadas tentativas de humor (uma ou outra boa). Na sequência, mostraram como resolver o problema usando anotações do WebBeans. Explicaram rapidamente que WebBeans é a implementação de referência da JSR-299 que se propõe a padronizar a forma como injeção de dependências deve ser feita em Java. Em seguida mostraram uma demo que funcionou corretamente. Acabaram pouco de Seam, apenas disseram que o core do Seam em sua próxima versão será o WebBeans e mostraram algumas features adicionais. No geral a apresentação foi melhor que a anterior embora tenham mal aproveitado o tempo.<br /><br /><b>"VRaptor 3: Guerrilha Web" por Felipe Sabella e Guilherme Silveira</b><br /><br /> Infelizmente voltamos do almoço apenas a tempo de pegar o final da palestra. A apresentação mostrou o VRaptor que está estreiando sua versão 3.0. O VRaptor é um framework MVC desenvolvido pelo pessoal da Caelum com foco em Ajax, rich interfaces, REST e integração com outros frameworks.<br /><br /><b>Arquitetura para aplicações Java de médio porte por Guilherma Moreira e Segio Lopes</b><br /><br /> Apresentação ruim. Novamente ficou clara a falta de preparo. Perderam tempo com encenações e as demos não funcionaram corretamente. Deram algumas dicas de Hibernate para resolução de problemas comuns:<br /> - commit + clear para limpar o transaction log e o persistence context evitando um demasiado uso de memória e consequente diminuição de performance por conta de "garbage collection"<br /> - uso de stateless session para inserts em massa<br /><br /><b>Para onde vai a plataforma Java? Linguagens dinâmicas, JavaTV, JavaFX e além! por Anderson Leite e Fabio Kung</b><br /><br /> Apresentação regular. Explicaram como são feitas chamadas a métodos no bytecode em diversos casos (invokestatic, invokespecial, invokevirtual e o novo invokedynamic que será introduzido no Java7). Depois disso abordaram funcionalidades encontradas em linguagens dinâmicas como Closures. Mostraram as propostas de inclusão de Closures em Java (BGGA, CICE e FCM) porém com péssimos exemplos que não demonstraram o real poder que este recurso permite. Do jeito que foi colocado pareceu que closures em Java seriam apenas um jeito mais bizarro de se escrever as mesmas coisas. Isto é péssimo pois quem não tinha tido contato com este tipo de construção antes ficou com uma impressão completamente equivocada. No fim, por terem perdido tempo nos tópicos anteriores não falaram de JavaTV e nem de JavaFX apenas citando rapidamente o Ginga-NCL e o GingaJ (<a href="http://www.ginga.org.br/" target="_blank">http://www.ginga.org.br/</a>).<br /><br /><b>GET /Connected por Jim Webber</b><br /><br /> Ótima apresentação. Após um dia inteiro de palestras regulares ou inconsistentes foi refrescante ter encerrado com mais uma boa palestra de Jim Webber. Novamente o palestrante demonstrou excelente preparo inclusive com improvisações muito bem encaixadas. Jim continuou falando de "Web Enabled Services" com REST. Seguiu defendendo a Web como o middleware perfeito para este cenário sem necessidade de outros frameworks realizarem a comunicação. Não chegou a dar um exemplo prático mas explicou com maiores detalhes como funcionariam por exemplo pedidos de café numa cafeteria qualquer usando REST, basicamente um case CRUD. Mostrou como seriam feitos a inserção, alteração e remoção do pedido e o que aconteceria em casos inválidos (por exemplo a tentativa de alteração de um pedido já preparado).<br /><br /> Para encerrar este longo primeiro post posso dizer que a ida ao evento valeu a pena, principalmente por conta das palestras do Jim Webber.<div class="blogger-post-footer">Dev@Maps</div>jrenauthttp://www.blogger.com/profile/16232874619067763399noreply@blogger.com0