Criação da Classe através de um Objeto Serializado

Olá Pessoal!

Segue uma questão um pouco maluca :oops: : quando eu tenho um objeto serializado, eu só consigo instancia-lo caso eu tenha a sua classe original. Existe alguma ferramenta que cria uma classe em tempo de execução a partir de um objeto serializado? Esclarecendo: eu quero carregar as informações de um objeto serializado que eu não tenho a classe. Tem alguma ferramenta que criaria uma classe com base nas informações do objeto serializado, a carregaria, instanciaria e popularia com as informações -> tudo isso um com base nas informações daquele objeto serializado?

Qualquer ajuda será bem vinda!!! :lol:

Eduardo,
Acho que é impossível. Na serialização, você tem os nomes e valores dos atributos. Mas como você saberia os nomes e, principalmente, a implementação dos métodos?

[quote=cristianomariano]Eduardo,
Acho que é impossível. Na serialização, você tem os nomes e valores dos atributos. Mas como você saberia os nomes e, principalmente, a implementação dos métodos?[/quote]

Olá Cristiano!

Na verdade a intenção não seria recuperar as classes originais com os métodos, mas somente as informações. Essa classe alternativa que seria criada teria somente os atributos e talvez um get/set para cada um deles. O objetivo seria, por exemplo, poder interagir com um serviço RMI sem ter as classes utilizadas como parâmetro e retorno.

1º Reflexão:

Dada uma classe serializável, mas com uma superclasse NÃO serializável, quaisquer variáveis de instância que a primeira Herdar da superclasse serão resetadas aos valores que receberam durante a construção original do objeto.Isso ocorre porque o construtor da Classe não-serializável irá rodar.

Na verdade, todo construtor Acima do construtor da primeira classe não-serializável também rodará, de uma forma ou de outra, porque, depois que o primeiro construtor for chamado, ele obviamente chama o seu super construtor e assim por diante na árvore de herença.

  1. [size=18]Entendimento :[/size]

:idea: 1º Situação

:arrow: Criar uma classe com base nas informações do objeto serializado :?:

:arrow: carregaria
:arrow: instanciaria
:arrow: popularia com as informações

2º Reflexão:

Quando um objeto é des-serializado, nós NÃO queremos que a inicialização normal aconteça.Não queremos que os construtores rodem, e não queremos que os valores explicitamente declarados sejam atribuídos.Queremos apenas que os valores sejam salvos como parte do estado serializado do objeto a ser re-atribuído.

:idea: 2º Situação

Obter informações objeto serializado, sem a sua classe original, usando referência em seu estado como objeto serializado :?:

:idea: 3º Reflexão:

O Modificador transient só pode ser aplicado a variáveis de instância.

:idea: 4º Reflexão

Variáveis Transientes

Se marcar uma variável de instância como transiente, você estará dizendo à JVM para pular(ignorar) essa variável quando você tentar serializar o objeto que a contém.

[size=16]flatten[/size] Um Objeto escrendo o seu estado.

:arrow: O valor das suas variáveis de instância em um tipo especial de stream de E/S.

[size=14]1º Conclusão [/size]

:stuck_out_tongue: Acredito que sim, exista um mecanismo para trabalhar com tipo especial de E/S, já base nas informações daquele objeto serializado.

[quote=Marcio Duran]

[size=14]1º Conclusão [/size]

:stuck_out_tongue: Acredito que sim, exista um mecanismo para trabalhar com tipo especial de E/S, já base nas informações daquele objeto serializado.[/quote]

Olá Marcio!

Eu acredito que seja possível implementar, porém não sei se alguém já criou esse mecanismo… Alguém conhece alguma coisa?

Não daria pra dar um load no objeto como Object mesmo e usar reflection para obter os valores?

Se você fizer isso e não tiver a classe no classpath, será lançado um ClassCastException

Suponha que a classe não dependa de outras (exceto as que existem em java., javax. etc.).

Neste caso, acho perfeitamente possível. Vamos dar um exemplo.

Digamos que você tenha uma classe br.com.exemplo.Cliente com o seguinte layout:

package br.com.exemplo;
import java.io.*;
import java.util.*;

public class Cliente implements Serializable {
    private long id;
    private String nome, endereco, telefone;
    private double limiteCredito;
    private transient Date hoje = new Date();
    public Cliente (long id, String nome, String endereco, String telefone, double limiteCredito) {
	this.id = id; this.nome =  nome; this.endereco = endereco; this.telefone = telefone; this.limiteCredito = 

limiteCredito;        
    }
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("teste.ser"));
        oos.writeObject (new Cliente (0xCAFEBABE, "João", "R dos Bobos 0", "5555-5555", 1.23));
        oos.close();
    }
}

O resultado de rodar este programa é um arquivo “teste.ser”, que iremos mostrar em hexadecimal:

0000	AC ED 00 05 73 72 00 16  62 72 2E 63 6F 6D 2E 65   .í..sr..br.com.e
0010	78 65 6D 70 6C 6F 2E 43  6C 69 65 6E 74 65 BE 45   xemplo.Cliente.E
0020	B6 32 72 E3 93 FA 02 00  05 4A 00 02 69 64 44 00   .2rã.....J..idD.
0030	0D 6C 69 6D 69 74 65 43  72 65 64 69 74 6F 4C 00   .limiteCreditoL.
0040	08 65 6E 64 65 72 65 63  6F 74 00 12 4C 6A 61 76   .enderecot..Ljav
0050	61 2F 6C 61 6E 67 2F 53  74 72 69 6E 67 3B 4C 00   a/lang/String;L.
0060	04 6E 6F 6D 65 71 00 7E  00 01 4C 00 08 74 65 6C   .nomeq.~..L..tel
0070	65 66 6F 6E 65 71 00 7E  00 01 78 70 FF FF FF FF   efoneq.~..xp....
0080	CA FE BA BE 3F F3 AE 14  7A E1 47 AE 74 00 0D 52   .þ..?ó..z.G.t..R
0090	20 64 6F 73 20 42 6F 62  6F 73 20 30 74 00 05 4A    dos Bobos 0t..J
00A0	6F C3 A3 6F 74 00 09 35  35 35 35 2D 35 35 35 35   o..ot..5555-5555

Como vemos, ele tem várias informações. Uma delas é que o nome da classe está disponível, assim como os nomes dos campos serializados e dos tipos dos campos e, obviamente, os valores. Basta ter um pouco de paciência (e ler o fonte de ObjectOutputStream, é claro) para ver como é possível “reconstruir” os dados.
A propósito, eu não poderia usar ObjectInputStream para efetuar essa reconstrução? Não exatamente, porque ele tentaria recriar um objeto br.com.exemplo.Cliente, mas ele precisa dispor da classe real (br.com.exemplo.Cliente) no CLASSPATH; se não conseguir, ele acaba gerando uma ClassNotFoundException.
Você poderia modificar ObjectInputStream para criar uma outra coisa (talvez um HashMap<String,Object> mapeando nomes de campos a seus respectivos valores) se a tal classe não estiver disponível para você.

:idea: Localizei a ferramenta através de um NetWork de confiança, no entanto já me alertaram que é uma manobra arriscada de se fazer.Todavia Eduardo gostaria de sua opinião para o seu real uso.
Abaixo, da ferramenta.

ASM is an all purpose Java bytecode manipulation and analysis framework.

Solução
http://asm.objectweb.org/

Pois é, o Marcio Duran respondeu que com o ASM, ou então com algum outro framework de criação de classes (como o Javassist, em http://www.csg.is.titech.ac.jp/~chiba/javassist/ ou http://www.jboss.org/javassist/ ) que poderia também ser usado, você poderia criar uma instância de uma classe que não seria exatamente a mesma classe original (como você deve ter visto no meu exemplo, o valor transiente “hoje” não é armazenado durante a serialização) , mas seria equivalente em termos de “ambas as classes serializam para o mesmo formato”.

O ASM é excelente mesmo (inclusive na próxima MundoJava tem um artigo meu sobre ele) e poderia sem problemas ser utilizado para criar uma classe em tempo de execução. O problema seria que isso daria um bom trabalho para fazer!!!

[quote=thingol]Pois é, o Marcio Duran respondeu que com o ASM, ou então com algum outro framework de criação de classes (como o Javassist, em http://www.csg.is.titech.ac.jp/~chiba/javassist/ ou http://www.jboss.org/javassist/ ) que poderia também ser usado, você poderia criar uma instância de uma classe que não seria exatamente a mesma classe original (como você deve ter visto no meu exemplo, o valor transiente “hoje” não é armazenado durante a serialização) , mas seria equivalente em termos de “ambas as classes serializam para o mesmo formato”.

[/quote]

Fiquei curioso com a questão, mas confesso que em termos de complexidade isso deva ser muito bem explorado.

Em termos de framework para efetuar tal mecanismo, não conhecia busquei informações de quem já utilizou-se desse instrumento(vamos colocar dessa forma),agora devo estar melhor situado.Ao seu exemplo fiz a observação sobre a questão sobre transiente, mas da maneira que o Eduardo colocou a proposta tive que ir atrás de melhores esclarecimentos..No entando busco, saber do que melhor do que se trata.

:!: É ai que está a questão !!?? , que eventos não previsíveis eu poderia ter com essa prática de criar classe em tempo de execução, Eduardo ?

:!: É ai que está a questão !!?? , que eventos não previsíveis eu poderia ter com essa prática de criar classe em tempo de execução, Eduardo ?

[/quote]

Uma questão que acho que seria cata de se lidar é em relação a termos uma mistura de objetos que temos as classes (Date, ArrayList) com objetos que não temos. Outro fator complicador, é se no objeto serializado houver a mesma instância referenciada mais de uma vez. Porém, nada que com um pouco de trabalho não seja possível fazer.

A API básica do Java não tem nenhum parser de objetos serializados? Isso ajudaria bastante!

Como eu disse, dê uma olhada no fonte de ObjectInputStream - olhar o fonte do JDK é meio tedioso mas é bastante didático. Provavelmente você acabaria efetuando um subclassing de java.io.ObjectInputStream, para poder criar as classes dinamicamente se elas não estiverem no seu CLASSPATH. Outra coisa chata é que você teria de efetuar um cache dessas classes, para não ter o famoso problema de “Person instanceof Person” == false.

:idea: Vou analisar melhor as questões desse fatores complicadores, mas se tal API não existia porque acho-se conveniente melhor o seu uso agora.

:arrow: No entando um estudo de viabilidade seria o melhor a se fazer desse FrameWork e suas limitações, frente melhores soluções à serem implementáveis.

:stuck_out_tongue: Resumindo, estarei pesquisando melhor o assunto !!!

:lol: :lol: :lol: :lol: :lol: