<?xml version="1.0" encoding="UTF-8"?>
<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/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.caelum.com.br &#187; stacktrace</title>
	<atom:link href="http://blog.caelum.com.br/tag/stacktrace/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.caelum.com.br</link>
	<description>blog dos desenvolvedores da Caelum</description>
	<lastBuildDate>Thu, 09 Feb 2012 13:04:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Java Puzzle: curiosidade com a eliminação das variáveis locais</title>
		<link>http://blog.caelum.com.br/java-puzzle-curiosidade-com-a-eliminacao-das-variaveis-locais/</link>
		<comments>http://blog.caelum.com.br/java-puzzle-curiosidade-com-a-eliminacao-das-variaveis-locais/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 22:00:58 +0000</pubDate>
		<dc:creator>Paulo Silveira</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[bloco]]></category>
		<category><![CDATA[bytecode]]></category>
		<category><![CDATA[gc]]></category>
		<category><![CDATA[java internals]]></category>
		<category><![CDATA[javac]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[pilha]]></category>
		<category><![CDATA[puzzle]]></category>
		<category><![CDATA[stacktrace]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/?p=777</guid>
		<description><![CDATA[A lista de emails interna de desenvolvedores da Caelum sempre foi muito ativa, e ultimamente anda aparecendo alguns dos clássicos Java Puzzlers para serem debatidos. O Márcio Hasegawa recentemente postou o problema mais recente da Java Specialists Newsletter: Problema Por que isso dá OutOfMemoryError? Repare que criamos duas arrays que gastarão mais da metade da <a href="http://blog.caelum.com.br/java-puzzle-curiosidade-com-a-eliminacao-das-variaveis-locais/#more-777'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>A lista de emails interna de desenvolvedores da Caelum sempre foi muito ativa, e ultimamente anda aparecendo alguns dos  clássicos Java Puzzlers para serem debatidos. O Márcio Hasegawa recentemente postou <a href="http://www.javaspecialists.eu/archive/Issue173.html">o problema mais recente da Java Specialists Newsletter</a>:</p>
<p><strong>Problema</strong></p>
<p>Por que isso dá <code>OutOfMemoryError</code>? Repare que criamos duas arrays que gastarão mais da metade da memória que temos, porém a primeira pode (?) ser captada pelo garbage collector, já que seu escopo termina logo:</p>
<pre class="brush: java; title: ; notranslate">
class JavaMemoryPuzzle {
  private final int dataSize = (int)
    (Runtime.getRuntime().maxMemory() * 0.6);

  public void f() {
    {
      byte[] data = new byte[dataSize];
    }

    byte[] data2 = new byte[dataSize];
  }

  public static void main(String[] args) {
    JavaMemoryPuzzle jmp = new JavaMemoryPuzzle();
    jmp.f();
  }
}
</pre>
<p>Já esse código, com um pequeno int i = 0 no meio, roda sem estourar a memória:</p>
<pre class="brush: java; title: ; notranslate">
class JavaMemoryPuzzlePolite {
  private final int dataSize = (int)
    (Runtime.getRuntime().maxMemory() * 0.6);

  public void f() {
    {
      byte[] data = new byte[dataSize];
    }

    int i = 0;

    byte[] data2 = new byte[dataSize];
  }

  public static void main(String[] args) {
    JavaMemoryPuzzlePolite jmp = new JavaMemoryPuzzlePolite();
    jmp.f();
    System.out.println(&quot;sem OutOfMemoryError&quot;);
  }
}
</pre>
<p><strong>Solução</strong></p>
<p>O Sérgio Lopes respondeu na lista de maneira muito apropriada. Utilizou o bytecode para justificar o comportamento do garbage collector. Vou parafrasea-lo a partir daqui:</p>
<p>Se você olhar o bytecode gerado dá pra ver a diferença (<code>javap -c Puzzle</code>). A versão sem declaração do <code>int </code> gera:</p>
<pre>
   0: aload_0
   1: getfield #24; //Field dataSize:I
   4: newarray byte
   6: astore_1
   7: aload_0
   8: getfield #24; //Field dataSize:I
   11: newarray byte
   13: astore_1
   14: return
</pre>
<p>Vemos que no <code>6</code> ele guarda a referência do primeiro array (<code>astore</code>) na variável local <code>_1</code> e depois ele cria o novo array na <code>11 </code>(<code>newarray</code>). O problema é que a variável <code>_1</code> ainda se referência para a primeira array, impedindo que o GC colete-a! <strong>Apenas depoisde já ter instanciado a segunda array</strong> ele guardará essa referência na mesma posição de variável local (<code>_1</code>). Nesse caso já é tarde demais e o heap estourou.</p>
<p>O bytecode da versão que não estoura é parecido, porém mostra  a <strong>variável local <code>int  i = 0</code> &#8220;reutilizando&#8221;</strong> o espaço da referência a primeira array e, portanto, liberando o objeto referenciado anteriormente naquela posição para uma possível coleta:</p>
<pre>
   0: aload_0
   1: getfield #24; //Field dataSize:I
   4: newarray byte
   6: astore_1
   7: iconst_0
   8: istore_1
   9: aload_0
   10: getfield #24; //Field dataSize:I
   13: newarray byte
   15: astore_2
   16: return
</pre>
<p>Reparem que em <code>6</code>  ele guarda a referência ao array na variável de posição <code>_1</code> e depois ele guarda <code>int</code> (que vale <code>0</code>, valor empilhado por <code>iconst_0</code>) na <strong>mesma</strong> posição (linha <code>8</code>), &#8220;reutilizando&#8221; o espaço da variável <strong>antes</strong> de criar outro array gigante. Nesse caso, a referência ao segundo array é colocada na variável local <code>_2</code> (linha 15).</p>
<p>Moral da história: só teremos liberadas as variáveis locais quando o método acaba e não quando os escopos acabam, mas o compilador pode &#8220;sem querer&#8221; liberar algumas no meio do caminho caso vá usar mais variáveis, reutilizando espaços não mais utilizados. Interessante!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/java-puzzle-curiosidade-com-a-eliminacao-das-variaveis-locais/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

