<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/wordpress-mu-1.2.5" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>procself &#187; java</title>
	<link>http://blogs.fe.up.pt/mpadilha</link>
	<description>cat /proc/self/cmdline</description>
	<pubDate>Wed, 14 Oct 2009 17:36:32 +0000</pubDate>
	<generator>http://wordpress.org/?v=wordpress-mu-1.2.5</generator>
	<language>en</language>
			<item>
		<title>Lapsed Listeners</title>
		<link>http://blogs.fe.up.pt/mpadilha/2009/10/06/lapsed-listeners/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2009/10/06/lapsed-listeners/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 13:55:13 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2009/10/06/lapsed-listeners/</guid>
		<description><![CDATA[Só uma nota muito rápida a propósito de uma memory leak que tive que identificar recentemente.
Até encontrar esta situação, todos os casos com que me tinha deparado eram sempre causados por uma colecção static que não estava a ser devidamente mantida. Esta situação, é ligeiramente diferente, no sentido em que a colecção em causa não [...]]]></description>
			<content:encoded><![CDATA[<p>Só uma nota muito rápida a propósito de uma <em>memory leak</em> que tive que identificar recentemente.</p>
<p>Até encontrar esta situação, todos os casos com que me tinha deparado eram sempre causados por uma colecção <i>static</i> que não estava a ser devidamente mantida. Esta situação, é ligeiramente diferente, no sentido em que a colecção em causa não é mantida directamente pela aplicação, mas sim pelo SWT. É um problema conhecido como &#8220;<em>Lapsed Listeners</em>&#8221; e está bem descrito aqui:</p>
<blockquote><p><a href="http://www.javaworld.com/javaworld/javatips/jw-javatip79.html?page=1">http://www.javaworld.com/javaworld/javatips/jw-javatip79.html?page=1</a></p></blockquote>
<p><a href="http://www.javaworld.com/javaworld/javatips/jw-javatip79.html?page=1"></a></p>
<p>Resumidamente: lembrem-se sempre de remover os <em>listeners</em> que já não são acessíveis, ou então implementem-nos com uma <a href="http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html">WeakReference</a>.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=111&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_111" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2009/10/06/lapsed-listeners/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Application Bundle Info.plist</title>
		<link>http://blogs.fe.up.pt/mpadilha/2009/08/24/application-bundle-infoplist/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2009/08/24/application-bundle-infoplist/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 17:25:16 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mac]]></category>

		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2009/08/24/application-bundle-infoplist/</guid>
		<description><![CDATA[Tenho estado a portar uma aplicação Java/SWT para Mac OSX e as coisas até têm estado a correr bem (depois de me ter resignado a usar Carbon em vez de Cocoa&#8230;). Isto claro, até me passar pela cabeça que precisava de alterar o comportamento do .app que o Product Export Wizard do Eclipse estava a [...]]]></description>
			<content:encoded><![CDATA[<p>Tenho estado a portar uma aplicação Java/SWT para Mac OSX e as coisas até têm estado a correr bem (depois de me ter resignado a usar Carbon em vez de Cocoa&#8230;). Isto claro, até me passar pela cabeça que precisava de alterar o comportamento do .app que o <a href="http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.pde.doc.user/guide/tools/export_wizards/export_product.htm">Product Export Wizard</a> do Eclipse estava a gerar.</p>
<p>Basicamente queria que em vez de ser invocado o executável que lança a JVM fosse primeiro chamado um <em>shell script</em> para fazer umas validações antes de chamar o executável. Pareceu-me que a forma correcta de o fazer seria editar o ficheiro:</p>
<blockquote><p> Info.plist</p></blockquote>
<p>dentro do <em>application bundle</em>, nomeadamente a propriedade:</p>
<blockquote><p>CFBundleExecutable</p></blockquote>
<p>que como o próprio nome sugere, indica qual é o executável que deve ser lançado quando o utilizador faz duplo-clique na aplicação em causa.</p>
<p>Infelizmente, por muito que alterasse a bendita propriedade, nada. O sistema continuava tranquilamente a invocar o executável. Aparentemente a alteração estava a ser ignorada por algum motivo.</p>
<p>Não foi fácil de encontrar, mas já alguém tinha tentado fazer o mesmo e obtido o mesmo resultado:</p>
<blockquote><p>Hi,<br />
I&#8217;m trying to customize the behavior of certain application bundles by editing the Info.plist preferences. The idea is to change the CFBundleExecutable key to point to a different file. Unfortunately, my changes seem to be ignored. &#8212; by Chadrik in <a href="http://discussions.apple.com/thread.jspa?threadID=1496021">Apple Support Forums</a></p></blockquote>
<p>E felizmente alguém tinha respondido:</p>
<blockquote><p>Some of those things are only read at startup or logiin, hence no change will happen until you logout or restart. &#8212; by BDAquain <a href="http://discussions.apple.com/thread.jspa?threadID=1496021">Apple Support Forums</a></p></blockquote>
<p>Enfim, só foi pena as horas perdidas&#8230; as caches são umas gajas lixadas&#8230; sobretudo quando não se sabe que elas existem <img src='http://blogs.fe.up.pt/mpadilha/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>Mas ainda assim, não há quem me convença que a coisa está mal feita&#8230; seria assim tão difícil ao leopardo, no momento em que guarda o ficheirito em cache registar-se na <a href="http://wiki.linuxquestions.org/wiki/FAM">FAM</a> (ou no kqueue <a href="http://lists.apple.com/archives/carbon-dev/2005/Nov/msg00890.html">que parece ser a alternativa</a> em Mac / BSD&#8230;) para receber notificações de alteração?</p>
<p>&nbsp;</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=110&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_110" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2009/08/24/application-bundle-infoplist/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Thread-safe singleton?</title>
		<link>http://blogs.fe.up.pt/mpadilha/2009/03/11/thread-safe-singleton/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2009/03/11/thread-safe-singleton/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 12:18:46 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[performance]]></category>

		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2009/03/11/thread-safe-singleton/</guid>
		<description><![CDATA[Uma das piores coisas que se pode encontrar quando se pretende migrar uma aplicação single-threaded para multi-threaded é um Singleton que nunca o deveria ter sido, um daqueles que guarda informação de estado por todo o lado e que é usado em múltiplos sítios da aplicação ao longo de todo o ciclo de vida.
O que [...]]]></description>
			<content:encoded><![CDATA[<p>Uma das piores coisas que se pode encontrar quando se pretende migrar uma aplicação single-threaded para multi-threaded é um Singleton que nunca o deveria ter sido, um daqueles que guarda informação de estado por todo o lado e que é usado em múltiplos sítios da aplicação ao longo de todo o ciclo de vida.</p>
<p>O que é se faz a uma coisa destas? A solução parece óbvia: &#8220;alteras o método instance() para devolver sempre um objecto novo&#8221;, efectivamente desfazendo o comportamento de singleton. Ok, funciona, mas e se o impacto em termos de performance for demasiado elevado? O que fazer quando se pretende manter o comportamento de singleton, mas ao nível do Thread, em vez de ser ao nível da JVM?</p>
<p>A resposta é substituir as variáveis existentes que guardam informação de estado por outras do tipo <a href="http://java.sun.com/javase/6/docs/api/java/lang/ThreadLocal.html">ThreadLocal&lt;T&gt;</a>.</p>
<blockquote><p>This class provides thread-local variables.  These variables differ from  their normal counterparts in that each thread that accesses one (via its  <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized  copy of the variable.  <tt>ThreadLocal</tt> instances are typically private  static fields in classes that wish to associate state with a thread (e.g.,  a user ID or Transaction ID).</p></blockquote>
<p>Ok, perfeito, não é?</p>
<p>Hmm&#8230; quase. Funciona bem se a criação dos threads for feita exclusivamente &#8220;antes&#8221; da primeira utilização da classe. Dessa forma cada thread inicializa a sua própria cópia uma só vez e trabalha com ela daí para a frente.</p>
<p>Mas e se forem necessários vários níveis de multi-threading, alguns dos quais &#8220;depois&#8221; da primeira utilização da classe? De acordo com a forma de funcionamento das variáveis ThreadLocal, cada thread filho teria uma instância nova, o que pode corresponder a esforço desnecessário e, dependendo dos casos, ter um impacto significativo no desempenho.</p>
<p>O nome diz tudo:  <a href="http://java.sun.com/javase/6/docs/api/java/lang/InheritableThreadLocal.html">InheritableThreadLocal&lt;T&gt;</a> é uma subclasse de ThreadLocal&lt;T&gt; que permite herdar a instância do thread pai se ela existir.</p>
<blockquote><p> This class extends <tt>ThreadLocal</tt> to provide inheritance of values  from parent thread to child thread: when a child thread is created, the  child receives initial values for all inheritable thread-local variables  for which the parent has values.  Normally the child&#8217;s values will be  identical to the parent&#8217;s; however, the child&#8217;s value can be made an  arbitrary function of the parent&#8217;s by overriding the <tt>childValue</tt>  method in this class.</p></blockquote>
<p>Agora sim, perfeito. <img src='http://blogs.fe.up.pt/mpadilha/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=99&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_99" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2009/03/11/thread-safe-singleton/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JDBC e Reverse DNS Lookups</title>
		<link>http://blogs.fe.up.pt/mpadilha/2009/03/09/jdbc-e-reverse-dns-lookups/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2009/03/09/jdbc-e-reverse-dns-lookups/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 18:53:42 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[performance]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[windows]]></category>

		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2009/03/09/jdbc-e-reverse-dns-lookups/</guid>
		<description><![CDATA[Se alguma vez ouvirem alguém queixar-se que uma aplicação Java client/server que funciona exclusivamente em rede local fica extraordinariamente lenta cada vez que o acesso à Internet cai, lembrem-se deste post.
Com uma descrição destas a primeira coisa que me ocorre é DNS. Como a aplicação não deixa de funcionar, fica simplesmente mais lenta, provavelmente o [...]]]></description>
			<content:encoded><![CDATA[<p>Se alguma vez ouvirem alguém queixar-se que uma aplicação Java client/server que funciona exclusivamente em rede local fica extraordinariamente lenta cada vez que o acesso à Internet cai, lembrem-se deste post.</p>
<p>Com uma descrição destas a primeira coisa que me ocorre é DNS. Como a aplicação não deixa de funcionar, fica simplesmente mais lenta, provavelmente o problema estará numa resolução inversa de DNS, que são frequentemente feitas pelas aplicações / middleware apenas para efeitos de logging.</p>
<p>Para não restarem dúvidas que o problema se relacionava com DNS, o servidor em causa tinha a configuração de DNS a apontar para o servidores do ISP, que obviamente ficam inacessíveis cada vez que se perde o acesso à Internet.</p>
<p>Comecei por procurar na aplicação, mas não encontrei nada que justificasse um lookup inverso de DNS. No tomcat encontrei um parâmetro que parecia promissor:</p>
<blockquote><p><code>enableLookups - Set to true if you want calls to request.getRemoteHost() to perform DNS lookups in order to return the actual host name of the remote client. Set to false to skip the DNS lookup and return the IP address in String form instead (thereby improving performance). By default, DNS lookups are enabled.</code></p></blockquote>
<p>Mas mesmo depois de desactivar o problema persistia. Descendo ainda mais na stack aplicacional descobri este <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5092063">bug</a> no Java, já antiguinho, mas ainda aplicável à versão que estava a ser usada:</p>
<blockquote><p><code>There is a call to InetSocketAddress.getHostName() in the ProxySelector code. This will trigger a reverse lookup when the hostname is not already known. If DNS is not configured correctly on the machine, this will generate a long timeout.</code></p></blockquote>
<p>Foi este <a href="http://archives.postgresql.org/pgsql-jdbc/2005-09/msg00094.php">post</a> na mailling list do Postgres que me conduziu ao bug em si e a descrição que fazem do problema é mais fácil de entender (e mais assustadora):</p>
<blockquote><p><code>I can confirm that this is an issue in JDK 1.5 (a/k/a Java5) in Windows.  This is not the fault of postgres, but like others have suggested, it is with reverse DNS lookup.  It affects all TCP connections.<br />
If you connect to an IP address it attempts to look up the name, resulting in these delays.</code></p></blockquote>
<p>Se actualizar a versão de Java não for uma hipótese viável (como não era no meu caso), e se a resolução inversa ocorrer sempre para o mesmo endereço IP ou conjunto restrito de endereços, a solução pode ser mesmo adicioná-los ao ficheiro de hosts (C:\windows\system32\drivers\etc\hosts ou /etc/hosts).</p>
<p>Pelo caminho ainda descobri uma forma fácil de ver o conteúdo da cache de DNS num sistema windows:</p>
<blockquote><p><code>ipconfig /displaydns</code></p></blockquote>
<p>Se ficaram curiosos sobre como fazer a mesma coisa em Linux, a resposta não é fácil. Sem software adicional o kernel Linux não inclui uma cache de DNS, cada pedido é um pedido. Existe o <a href="http://linux.die.net/man/8/nscd">nscd</a> (Name Server Cache Daemon) que é bastante comum mas não vem pré-instalado em todas as distribuições (por exemplo não vinha no último Debian que instalei).</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=100&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_100" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2009/03/09/jdbc-e-reverse-dns-lookups/feed/</wfw:commentRss>
		</item>
		<item>
		<title>JBoss + Hibernate + MySQL sem perder ligações</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 10:29:58 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[mysql]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[open-source]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/</guid>
		<description><![CDATA[Existem essencialmente duas formas distintas de usar Hibernate com MySQL (ou qualquer outra base-de-dados, para este ponto em concreto é indiferente), definindo todas as propriedades da ligação no próprio ficheiro de configuração do Hibernate, ou dizendo apenas que se pretende usar uma datasource JNDI pré-existente.
A primeira opção é a escolha típica numa aplicação stand-alone, mas [...]]]></description>
			<content:encoded><![CDATA[<p>Existem essencialmente duas formas distintas de usar Hibernate com MySQL (ou qualquer outra base-de-dados, para este ponto em concreto é indiferente), definindo todas as propriedades da ligação no próprio ficheiro de configuração do Hibernate, ou dizendo apenas que se pretende usar uma datasource JNDI pré-existente.</p>
<p>A primeira opção é a escolha típica numa aplicação stand-alone, mas a opção de utilizar uma datasource JNDI é a que faz mais sentido para <em>application servers</em>. Portanto, o ficheiro de configuração do Hibernate há-de ter, parcialmente, este aspecto:</p>
<p><code>&lt;hibernate-configuration&gt;<br />
&lt;session-factory&gt;<br />
&lt;property name="hibernate.connection.datasource"&gt;<br />
java:my_app_name<br />
&lt;/property&gt;<br />
&lt;property name="hibernate.setup"&gt;true&lt;/property&gt;<br />
&lt;property name="hibernate.dialect"&gt;<br />
org.hibernate.dialect.MySQLInnoDBDialect<br />
&lt;/property&gt;<br />
&lt;property name="transaction.factory_class"&gt;<br />
org.hibernate.transaction.JDBCTransactionFactory<br />
&lt;/property&gt;<br />
&lt;property name="current_session_context_class"&gt;<br />
thread<br />
&lt;/property&gt;<br />
&lt;/session-factory&gt;<br />
&lt;/hibernate-configuration&gt;</code></p>
<p>Depois basta definir a datasource com o nome JNDI correspondente, por exemplo assim:</p>
<p><code>&lt;datasources&gt;<br />
&lt;local-tx-datasource&gt;<br />
&lt;jndi-name&gt;my_app_name&lt;/jndi-name&gt;<br />
&lt;connection-url&gt;jdbc:mysql://host_or_ip/db_name&lt;/connection-url&gt;<br />
&lt;driver-class&gt;com.mysql.jdbc.Driver&lt;/driver-class&gt;<br />
&lt;user-name&gt;username&lt;/user-name&gt;<br />
&lt;password&gt;password&lt;/password&gt;<br />
&lt;min-pool-size&gt;5&lt;/min-pool-size&gt;<br />
&lt;max-pool-size&gt;20&lt;/max-pool-size&gt;<br />
&lt;/local-tx-datasource&gt;<br />
&lt;/datasources&gt;</code></p>
<p>Agora que está tudo montado como manda a documentação, sugiro uma experiência:</p>
<ol>
<li>Ligar servidor BD.</li>
<li>Ligar application server.</li>
<li>Testar aplicação que se liga à base de dados (funciona)</li>
<li>Reiniciar servidor BD (ou esperar 8 horas).</li>
<li>Testar aplicação que se liga à base de dados (não funciona!)</li>
</ol>
<p>Então&#8230; tanto trabalho para abstrair a ligação a base de dados e um simples restart da base de dados deixa as ligações geridas pelo Hibernate todas inválidas? E, pior, não há recuperação automática?</p>
<p>Pois&#8230; parece que não. E acrescentar o parâmetro <code>autoReconnect=true</code> ao URL JDBC também não resolve, aliás, a utilização desse parâmetro até é desaconselhada, como se pode ver pelo que diz no manual:</p>
<blockquote><p>Should the driver try to re-establish stale and/or dead connections? If enabled the driver will throw an exception for a queries issued on a stale or dead connection, which belong to the current transaction, but will attempt reconnect before the next query issued on the connection in a new transaction. The use of this feature is not recommended, because it has side effects related to session state and data consistency when applications don&#8217;t handle SQLExceptions properly, and is only designed to be used when you are unable to configure your application to handle SQLExceptions resulting from dead and stale connections properly. &#8212; <a href="http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html">MySQL 5.0 Reference Manual</a></p></blockquote>
<p>A solução que encontrei para MySQL (e que também funciona para MS SQL Server), é acrescentar a seguinte linha ao ficheiro de configuração da datasource:</p>
<p><code>&lt;check-valid-connection-sql&gt;SELECT 1&lt;/check-valid-connection-sql&gt;</code></p>
<p>Esta opção faz mesmo aquilo que parece fazer, ou seja, antes de usar uma ligação, a query ali especificada é executada como forma de verificar se a ligação é usável. Se não ocorrer nenhum erro, a instrução SQL que realmente se pretende executar é enviada pela mesma ligação, se houver um erro, a ligação é descartada e é criada uma nova.</p>
<p>Claro que isto tem um impacto sério na performance uma vez que se está a duplicar o número de queries, o que pode ser particularmente grave se o acesso à base de dados for feito através de um canal de elevada latência (rede, por exemplo).</p>
<p>Aparentemente existem soluções melhores para outras bases de dados, como o seguinte comentário parece sugerir:</p>
<p class="post-text">&nbsp;</p>
<blockquote><p>Whilst you can use the old &#8220;select 1 from dual&#8221; trick, the downside with this is that it issues an extra query each and every time you borrow a connection from the pool. For high volumes, this is wasteful.</p>
<p>JBoss provides a special connection validator which should be used for Oracle:</p>
<p>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</p>
<p>This makes use of the proprietary ping() method on the Oracle JDBC Connection class, and uses the driver&#8217;s underlying networking code to determine if the connection is still alive. &#8212; <a href="http://stackoverflow.com/questions/128527/is-there-any-way-to-have-the-jboss-connection-pool-reconnect-to-oracle-when-con#145889">stackoverflow.com</a></p></blockquote>
<p>Alguém conhece uma alternativa semelhante para MySQL?</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=96&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_96" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/11/28/jboss-hibernate-mysql-sem-perder-ligacoes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Eclipse Launcher</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/09/12/eclipse-launcher/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/09/12/eclipse-launcher/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 13:42:37 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[ibm]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/09/12/eclipse-launcher/</guid>
		<description><![CDATA[Algumas vez se perguntaram porque é que umas vezes o Eclipse arranca um único processo chamado &#8220;eclipse&#8221;, e outras vezes arranca dois processos, um chamado &#8220;eclipse&#8221; e outro chamado &#8220;javaw&#8221;? A resposta está aqui.
Resumidamente, quando o pedaço de código do eclipse que é nativo de cada plataforma consegue iniciar uma JVM por JNI, temos um único processo, [...]]]></description>
			<content:encoded><![CDATA[<p>Algumas vez se perguntaram porque é que umas vezes o Eclipse arranca um único processo chamado &#8220;eclipse&#8221;, e outras vezes arranca dois processos, um chamado &#8220;eclipse&#8221; e outro chamado &#8220;javaw&#8221;? A resposta está <a href="http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/misc/launcher.html">aqui</a>.</p>
<p>Resumidamente, quando o pedaço de código do eclipse que é nativo de cada plataforma consegue iniciar uma JVM por JNI, temos um único processo, quando não consegue usa os executáveis do JRE em causa, o que resulta num novo processo. Uma forma de forçar a invocação por JNI e, consequentemente, a existência de um único processo, é especificar a opção &#8220;-vm&#8221; na linha de comando ou no ficheiro eclipse.ini  e apontá-la directamente para o ficheiro jvm.dll (ou libjvm.so) do JRE em causa. Isto pode ser particularmente importante quando se tem que parar programaticamente o eclipse em plataformas que não sabem muito bem gerir a hierarquia entre processos (leia-se: Windows): <br />
<blockquote>The fundamental problem here is that, unlike Unix, Windows does that maintain parent-child relationships between processes. A process can kill its own immediate children, but unless you make other arrangements to obtain the information, can&#8217;t kill any &#8217;grand-children&#8217; because it has no way of finding them. Ctrl-C types at a command prompt is just a character that the command processor interprets and not a signal sent from outside. When you &#8216;destroy&#8217; a child command script, that process does not get the opportunity to terminate any child processes it may know about. Recent versions of WIndows (2000 or later) do provide a &#8220;Job&#8221; concept which acts as a container for processes. Killing a Job does terminate all processes associated with that job. However Jobs do not contain other jobs, so fully emulating the Unix behaviour is probably impossible. [Sun Bug ID: <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4770092">4770092</a>]      </p></blockquote>
<p>  </p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=93&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_93" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/09/12/eclipse-launcher/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Java Profilling - TPTP</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/09/03/java-profilling-tptp/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/09/03/java-profilling-tptp/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 16:45:09 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[performance]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[open-source]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/09/03/java-profilling-tptp/</guid>
		<description><![CDATA[Cada vez mais me convenço que, logo a seguir a um debugger, uma ferramenta de profiling é das mais importantes para quem desenvolve software.A minha mais recente descoberta é precisamente um profiler para aplicações Java desenvolvidas em (e/ou para) Eclipse. Chama-se TPTP, que é acrónimo para Testing and Performance Tools Platform, e foi um bocadinho difícil de pôr [...]]]></description>
			<content:encoded><![CDATA[<p>Cada vez mais me convenço que, logo a seguir a um debugger, uma ferramenta de <a href="http://en.wikipedia.org/wiki/Performance_analysis">profiling</a> é das mais importantes para quem desenvolve software.A minha mais recente descoberta é precisamente um <span class="Apple-style-span">profiler</span> para aplicações Java desenvolvidas em (e/ou para) Eclipse. Chama-se <a href="http://www.eclipse.org/articles/Article-TPTP-Profiling-Tool/tptpProfilingArticle.html">TPTP</a>, que é acrónimo para Testing and Performance Tools Platform, e foi um bocadinho difícil de pôr a funcionar em Vista por causa do <a href="http://technet.microsoft.com/en-us/library/cc709691.aspx">UAC</a>, mas valeu bem o esforço.Esta ferramenta permite analisar com muito detalhe a utilização de CPU. Dá para fazer <span class="Apple-style-span">drill-down</span> por package, classe e método; ver tempos gastos em cada nível da <span class="Apple-style-span">call stack</span>, ou acumulados daí para baixo; e até desenhar gráficos de chamadas e dependências (que me parecem pouco úteis para projectos já com alguma dimensão, mas enfim).Não explorei muito as capacidades de <span class="Apple-style-span">Memory Analysis</span>, porque não era o mais relevante para o projecto em causa, mas também estão lá. Só a <span class="Apple-style-span">performance</span> de rede é que não está contemplada nesta plataforma, mas para isso existem o <a href="http://jakarta.apache.org/jmeter/">JMeter</a> (se for HTTP) e o <a href="http://www.wireshark.org/">Wireshark</a> (em todos os outros casos), que fazem muito bem o seu trabalho. </p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=92&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_92" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/09/03/java-profilling-tptp/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Eclipse P2</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/08/20/eclipse-p2/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/08/20/eclipse-p2/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 11:20:49 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[open-source]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/08/20/eclipse-p2/</guid>
		<description><![CDATA[Apenas uma nota muito rápida sobre a mais recente versão do Eclipse: Ganymede.
Uma das novidades é o novo sistema de actualizações de plugins e features, o P2. Vale a pena ler este artigo, sobretudo para quem desenvolve plugins para o dito.
Partilhar
]]></description>
			<content:encoded><![CDATA[<p>Apenas uma nota muito rápida sobre a mais recente versão do Eclipse: <a href="http://www.eclipse.org/ganymede/">Ganymede</a>.</p>
<p>Uma das novidades é o novo sistema de actualizações de <em>plugins </em>e <em>features</em>, o P2. Vale a pena ler <a href="http://wiki.eclipse.org/Equinox_p2_Getting_Started">este artigo</a>, sobretudo para quem desenvolve <em>plugins </em>para o dito.</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=91&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_91" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/08/20/eclipse-p2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>EBCDIC String Sorting</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/08/14/ebcdic-string-sorting/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/08/14/ebcdic-string-sorting/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 15:12:47 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[java]]></category>

		<category><![CDATA[ibm]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/08/14/ebcdic-string-sorting/</guid>
		<description><![CDATA[Uma das muitas diferenças entre sistemas baseados em ASCII (ou qualquer dos seus super-sets) e os sistemas IBM - os mais tradicionais -, é que estes baseiam-se em EBCDIC, um sistema de codificação de caracteres de 8 bits que já vem do tempo dos cartões perfurados.
Essa herança tem uma consequência interessante: as letras do alfabeto [...]]]></description>
			<content:encoded><![CDATA[<p>Uma das muitas diferenças entre sistemas baseados em ASCII (ou qualquer dos seus <em>super-sets</em>) e os sistemas IBM - os mais tradicionais -, é que estes baseiam-se em <a href="http://en.wikipedia.org/wiki/EBCDIC">EBCDIC</a>, um sistema de codificação de caracteres de 8 bits que <a href="http://www.cs.uiowa.edu/~jones/cards/codes.html">já vem do tempo dos cartões perfurados</a>.</p>
<p>Essa herança tem uma consequência interessante: as letras do alfabeto não têm todas códigos consecutivos. Existe um intervalo entre a letra &#8216;I&#8217; e a letra &#8216;J&#8217;, por exemplo. Outra característica interessante é que os códigos correspondentes aos dígitos 0-9 são maiores do que os códigos de todas as letras do alfabeto, enquanto que em ASCII acontece o oposto. Também os sinais de pontuação aparecem em posições relativas diferentes, assim como os caracteres acentuados.</p>
<p>Para referência, aqui ficam links para as duas tabelas: <a href="http://en.wikipedia.org/wiki/EBCDIC_037">EBCDIC (codepage 037)</a> e <a href="http://www.asciitable.com/">ASCII</a>.</p>
<p>Em EBCDIC, a sequência efectiva de caracteres de acordo com o seu código numérico é a seguinte:</p>
<blockquote><p> âäàáãåçñ¢.&lt;(+|&amp;éêëèíîïìß!$*);¬-/ÂÄÀÁÃÅÇÑ¦,%_&gt;?øÉÊËÈÍÎÏÌ`:# \</p>
<p>@&#8217;=&#8221;Øabcdefghi«»ðýþ±°jklmnopqrªºæ¸Æ€µ~stuvwxyz¡¿ÐÝÞ®^£ \</p>
<p>¥·©§¶¼½¾[]¯¨´×{ABCDEFGHI­ôöòóõ}JKLMNOPQR¹ûüùúÿ\÷S \</p>
<p>TUVWXYZ²ÔÖÒÓÕ0123456789³ÛÜÙÚŸ</p></blockquote>
<p>Interessante, não? Os caracteres acentuados aparecem nos &#8220;intervalos&#8221;da tabela original&#8230;</p>
<p>Mas de facto, do ponto de vista prático, a consequência mais importante desta diferença é a seguinte: Uma aplicação baseada, por exemplo, em <a href="http://en.wikipedia.org/wiki/AS/400">AS/400</a> apresenta uma listagem ordenada de forma diferente de uma aplicação escrita em Java. Em ambientes de migração esta diferença pode ter consequências drásticas para utilizadores que, por exemplo, tiram partido de o <em>underscore</em> aparecer antes das letras do alfabeto, para dessa forma criarem elementos que aparecem sempre à cabeça de uma lista.</p>
<p>Uma forma de, para o bem ou para o mal, passar a ordenar Strings de acordo com a tabela EBCDIC é implementar um <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Comparator.html">Comparator</a> que use um <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/RuleBasedCollator.html">RuleBasedCollator</a> criado especificamente com a sequência de caracteres EBCDIC.</p>
<p>Por exemplo assim:</p>
<p><code><br />
String ebcdic_rules = "&lt; â &lt; à &lt; á &lt; ã &lt; ç &lt; ñ &lt; '.' &lt; '&lt;' &lt; '(' &lt; '+' &lt; '|' &lt; '&amp;' &lt; é &lt; ê &lt; è &lt; í &lt; î &lt; ì &lt; '!' &lt; '$' &lt; '*' &lt; ')' &lt; ';' &lt; '-' &lt; '/' &lt; Â &lt; À &lt; Á &lt; Ã &lt; Ç &lt; Ñ &lt; ',' &lt; '%' &lt; '_' &lt; '&gt;' &lt; '?' &lt; É &lt; Ê &lt; È &lt; Í &lt; Î &lt; Ì &lt; '`' &lt; ':' &lt; '#' &lt; '@' &lt; ''' &lt; '=' &lt; '\"' &lt; a &lt; b &lt; c &lt; d &lt; e &lt; f &lt; g &lt; h &lt; i &lt; '«' &lt; '»' &lt; j &lt; k &lt; l &lt; m &lt; n &lt; o &lt; p &lt; q &lt; r &lt; ª &lt; º &lt; '€' &lt; '~' &lt; s &lt; t &lt; u &lt; v &lt; w &lt; x &lt; y &lt; z &lt; '^' &lt; '£' &lt; '[' &lt; ']' &lt; '´' &lt; '{' &lt; A &lt; B &lt; C &lt; D &lt; E &lt; F &lt; G &lt; H &lt; I &lt; ô &lt; ò &lt; ó &lt; õ &lt; '}' &lt; J &lt; K &lt; L &lt; M &lt; N &lt; O &lt; P &lt; Q &lt; R &lt; û &lt; ù &lt; ú &lt; '\\' &lt; S &lt; T &lt; U &lt; V &lt; W &lt; X &lt; Y &lt; Z &lt; Ô &lt; Ò &lt; Ó &lt; Õ &lt; 0 &lt; 1 &lt; 2 &lt; 3 &lt; 4 &lt; 5 &lt; 6 &lt; 7 &lt; 8 &lt; 9 &lt; Û &lt; Ù &lt; Ú";</code></p>
<p><code>Collator collator = new RuleBasedCollator(ebcdic_rules);</code></p>
<p><code>if(collator.compare(a, b) &lt; 0){</code><br />
<code>    //a is less than b according to EBCDIC sorting criteria</code><br />
<code>} else {</code><br />
<code>    //a is equal or greater than b</code><br />
<code>}</code></p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=90&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_90" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/08/14/ebcdic-string-sorting/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Streams, Readers, RandomAccessFiles</title>
		<link>http://blogs.fe.up.pt/mpadilha/2008/07/18/streams-readers-randomaccessfiles/</link>
		<comments>http://blogs.fe.up.pt/mpadilha/2008/07/18/streams-readers-randomaccessfiles/#comments</comments>
		<pubDate>Fri, 18 Jul 2008 15:24:54 +0000</pubDate>
		<dc:creator>Manuel Padilha</dc:creator>
		
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blogs.fe.up.pt/mpadilha/2008/07/18/streams-readers-randomaccessfiles/</guid>
		<description><![CDATA[Imaginem que tinham que implementar um visualizador paginado de documentos de texto. Para simplificar vamos supôr que só é possível ver uma página inteira de cada vez, e que as páginas são constituídas por um número fixo de linhas.
As funcionalidades que este visualizador deve disponibilizar são extremamente simples:

Quando aberto pela 1ª vez deve mostrar a [...]]]></description>
			<content:encoded><![CDATA[<p>Imaginem que tinham que implementar um visualizador paginado de documentos de texto. Para simplificar vamos supôr que só é possível ver uma página inteira de cada vez, e que as páginas são constituídas por um número fixo de linhas.</p>
<p>As funcionalidades que este visualizador deve disponibilizar são extremamente simples:</p>
<ol>
<li>Quando aberto pela 1ª vez deve mostrar a 1ª página do documento.</li>
<li>Deve disponibilizar um botão para avançar uma página.</li>
<li>Deve disponibilizar um botão para retroceder uma página, se não se encontrar já na 1ª página.</li>
</ol>
<p>Para além disto, há um requisito não-funcional a ter em conta:</p>
<ul>
<li>Deve ser possível e eficiente visualizar e navegar num ficheiro com dimensão muito superior à memória disponível para o processo.</li>
</ul>
<p>Se tivessem que implementar uma coisa destas em Java, e esquecendo por completo a componente gráfica, que classes do JDK usariam para ler o ficheiro?</p>
<p>A resposta mais imediata é provavelmente uma conjugação de um <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/BufferedReader.html">BufferedReader</a>  com um qualquer tipo de <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/InputStream.html">InputStream</a>. Partindo desta ideia, implementar a funcionalidade 2 é muito simples, mas como fazer para implementar a 3? Acumular as páginas que já se avançou em memória não é razoável, porque esbarra no requisito não-funcional. Voltar ao início do documento e avançar <em>n-1</em> páginas também não, pelo mesmo motivo. O que fazer se não é possível navegar &#8220;para trás&#8221; num InputStream?</p>
<p>Há uma classe que parece ser a solução, mas de facto não é. O <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/PushbackInputStream.html">PushBackInputStream</a> permite fazer <code>unread()</code> de bytes lidos de um InputStream, mas guarda-os num buffer em memória, por isso não é viável.</p>
<p>A solução que encontrei está numa classe que já vem do JDK 1.0: <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/RandomAccessFile.html">RandomAccessFile</a>. Esta classe disponibiliza um método <code>seek()</code> para posicionar em qualquer ponto do ficheiro, e os habituais métodos <code>read()</code> e <code>readLine()</code>.</p>
<p>Há apenas dois problemas com esta abordagem:</p>
<ul>
<li>Deveria ser possível especificar o <em>encoding</em> que se pretende usar ao manipular um ficheiro, por exemplo no construtor da classe, ou em última análise como parâmetro dos métodos de leitura/escrita. Tal não é possível, o que significa que é necessário garantir que os ficheiros se encontram no <em>encoding</em> do sistema, ou alternativamente alterar o <em>encoding</em> do sistema para que corresponda ao do ficheiro. O método <code>readUTF()</code> poderia resolver este problema, não fosse a limitação de obrigar a ler o ficheiro todo de uma só vez.</li>
<li>O método <code>seek()</code> só aceita como parâmetro o <em>offset</em> em bytes desde o início do ficheiro. Seria útil, para além de poder especificar um <em>offset</em> relativo à posição actual, especificar um <em>offset</em> por exemplo em número de linhas (embora do ponto de vista de implementação isso tivesse que ser feito de forma radicalmente diferente de um <code>seek()</code> normal).</li>
</ul>
<p>Alguém tem sugestões de implementação melhores? Agradeciam-se&#8230;</p>
<p class="akst_link"><a rel="nofollow" href="http://blogs.fe.up.pt/mpadilha/?p=81&amp;akst_action=share-this"  title="Enviar por email, adicionar ao del.icio.us, ..." id="akst_link_81" class="akst_share_link">Partilhar</a>
</p>]]></content:encoded>
			<wfw:commentRss>http://blogs.fe.up.pt/mpadilha/2008/07/18/streams-readers-randomaccessfiles/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
