<?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; serialization</title>
	<atom:link href="http://blog.caelum.com.br/tag/serialization/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>Entendendo o serialVersionUID</title>
		<link>http://blog.caelum.com.br/entendendo-o-serialversionuid/</link>
		<comments>http://blog.caelum.com.br/entendendo-o-serialversionuid/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 11:21:57 +0000</pubDate>
		<dc:creator>Paulo Silveira</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[fj-31]]></category>
		<category><![CDATA[InvalidClassException]]></category>
		<category><![CDATA[java.io.InvalidClassException]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[Serializable]]></category>
		<category><![CDATA[serialização]]></category>
		<category><![CDATA[serialization]]></category>
		<category><![CDATA[serialVersionUID]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/2008/04/01/entendendo-o-serialversionuid/</guid>
		<description><![CDATA[O serialVersionUID é uma dúvida constante entre muitos desenvolvedores. Afinal, quando e para que exatamente usá-lo? Devo gerar um número aleatório bem grande, ou um número qualquer? Essas perguntas são comuns, e ao desenvolvedor experiente é necessário conhecer a fundo esse detalhe do processo de serialização do Java. Quando um objeto é serializado no Java, <a href="http://blog.caelum.com.br/entendendo-o-serialversionuid/#more-205'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>O <code>serialVersionUID</code> é uma dúvida constante entre muitos desenvolvedores. Afinal, quando e para que exatamente usá-lo? Devo gerar um número aleatório bem grande, ou um número qualquer? Essas perguntas são comuns, e ao desenvolvedor experiente é necessário conhecer a fundo esse detalhe do <a href="http://java.sun.com/javase/6/docs/platform/serialization/spec/serialTOC.html">processo de serialização do Java</a>.</p>
<p>Quando um objeto é serializado no Java, essa sequência de bytes, além de conter seus atributos de instância não transientes, carrega consigo um número que indentifica a &#8220;versão&#8221; da classe que foi usada durante o processo. Esse é o chamado <code>serialVersionUID</code>, ou seja, o indentificador de versão de serialização de uma classe. Esse número é utilizado para saber se o objeto que estamos recuperando é de uma versão &#8220;compatível&#8221; com a versão da classe que foi utilizada quando serializamos o objeto: em outras palavras, os arquivos <code>.class</code> não precisam ser necessariamente os mesmos para que o processo de serialização ocorra com sucesso. </p>
<p>Por exemplo, considere a seguinte classe <code>Usuario</code>:</p>
<pre class="brush: java; title: ; notranslate">
package br.com.caelum;

public class Usuario implements Serializable {
  private String login;
}
</pre>
<p>Essa classe possui o <code>serialVersionUID</code> igual a <code>2806421523585360625L</code>. <strong>Esse número não é aleatório</strong>! Ele é um hash (SHA) calculado em cima dos nomes dos seus atributos, e assinaturas dos métodos em uma ordem bem definida <a href="http://java.sun.com/javase/6/docs/platform/serialization/spec/class.html#4100">pela especificação do processo de serialização</a>.  E como eu sei esse número? O JDK vem com a ferramenta <code>serialver</code>, que implementa esse mesmo hash:</p>
<p><code>serialver br.com.caelum.Usuario</code></p>
<p>Se o <code>serialVersionUID</code> utilizado durante a serialização não bater exatamente com o <code>serialVersionUID</code> da classe que está sendo usada para recuperar essa informação, uma exception é lançada: <code>java.io.InvalidClassException</code>. </p>
<p>Por exemplo, se adicionarmos um novo atributo na nossa classe <code>Usuario</code>:</p>
<pre class="brush: java; title: ; notranslate">
public class Usuario implements Serializable {
  private String login;
  private String senha;
}
</pre>
<p>Agora teremos o <code>serialVersionUID</code> valendo <code>416295346730660862L</code>. Caso você serialize um <code>Usuario</code> com a primeira classe aqui definida, e tentar recuperar essa informação usando essa nova versão de classe, receberemos a conhecida <code>java.io.InvalidClassException</code>. Esse é o comportamente que em muitos casos queremos, mas algumas vezes fazemos pequenas modificações na classe as quais  percebemos que não impactarão no processo de serialização, e precisamos manter compatibilidade com a versão antiga daquela classe. Para isso, basta definirmos explicitamente qual é o nosso <code>serialVersionUID</code>, e no caso de querer manter compatibilidade com a classe <code>Usuario</code> anterior, vamos utilizar o valor de <code>serialVersionUID</code> que seria gerado pela JVM: <code>2806421523585360625L</code>. O código ficaria:</p>
<pre class="brush: java; title: ; notranslate">
public class Usuario implements Serializable {
  private static final long serialVersionUID = 2806421523585360625L;
  private String login;
  private String senha;
}
</pre>
<p>Às vezes recebemos um warning do Eclipse, e ele pede para que seja definido o <code>serialVersionUID</code>  da classe em questão. Isso ocorre porque você implementa <code>Serializable</code> ou uma de suas mães a implementa. O Eclipse então te abre três opções: utilizar o <code>@SurpressWarnings</code> para você assumir o risco, usar um valor default, ou usar o valor gerado. O gerador de UIDs do Eclipse é exatamente o mesmo gerador utilizado pelo Java SE para criar os UIDs padrão! Reforçando, <strong>esse número não é um número aleatório</strong>!</p>
<p>Quando alguém esquece de manter o mesmo <code>serialVersionUID</code> para duas versões compatíveis de uma classe, podemos ter problemas em usar diferentes versões do software que são teoricamente compatíveis. Isso muitas vezes acontece em servidores de aplicação, e se seu cliente esta desatualizado em relação a versão dos jars necessários pelo servidor, podemos ter alguns <code>InvalidClassException</code>s que poderiam ser facilmente evitados se o <code>serialVersionUID</code> tivesse sido corretamente aplicado. Claro que algumas outras vezes as versões realmente não são compatíveis e a exception procede.</p>
<p>Esse grave problema pode acontecer mesmo usando classes do Java SE entre diferentes versões, como é o caso da classe <code><a href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/AttributedCharacterIterator.Attribute.html">java.text.AttributedCharacterIterator.Attribute</a></code> (utilizada pela <code>java.awt.Font</code>). Do Java 1.3 para o Java 1.4 essa classe foi levemente alterada, e o <code>serialVersionUID</code> <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4365406">gerado pelo algoritmo da JVM desta classe mudou</a> de <code>-1514471214376796190L</code> para <code>-9142742483513960612L</code>.  Quando alguém serializava uma <code>java.awt.Font</code> em uma versão não podia desserializa-la em outra, sendo que as versões tecnicamente são compatíveis: a não definição explícita do <code>serialVersionUID</code> gerou um bug no Java SE. Como isto foi resolvido? Definiram o <code>serialVersionUID</code> como <code>-1514471214376796190L</code>, que é o valor que seria gerado pela JVM na versão anterior da classe.</p>
<p>Como então devemos proceder para escolher um <code>serialVersionUID</code> apropriado? É muito simples: se essa classe está nascendo neste momento, você pode se dar ao luxo de utilizar um <code>serialVersionUID</code>, como por exemplo:</p>
<pre class="brush: java; title: ; notranslate">
public class Usuario implements Serializable {
  private static final long serialVersionUID = 1L;
  private String login;
}
</pre>
<p>Porém se você está definindo o <code>serialVersionUID</code> de uma classe já em produção, e sabe que a mudança que está fazendo é compatível com a versão anterior, você deve utilizar o <code>serialVersionUID</code> que seria gerado pela JVM na primeira versão, como foi o caso aqui quando adicionamos o atributo <code>senha</code> na classe <code>Usuario</code>, e também foi o caso da correção do bug da classe <code>java.text.AttributedCharacterIterator.Attribute</code>. Quando você fizer uma alteração onde percebe que o cliente precisará de atualização das classes envolvidas, basta definir um <code>serialVersionUID</code> diferente dos anteriormente utilizados.</p>
<p>Para completar, implementar uma interface que não define métodos (<code>Serializable</code>) e ser forçado a escrever um atributo sem um contrato mais burocrático é um tanto estranho em uma linguagem como o Java. Sem dúvida, se esse mecanismo todo tivesse sido inventado já com a existência de anotações, <code>Serializable</code> seria uma anotação e <code>version</code> um atributo dela, talvez obrigatório, criando algo como <code>@Serializable(version=12345L)</code>. Boas serializações e invocações remotas!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/entendendo-o-serialversionuid/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
	</channel>
</rss>

