Object do Stack

16 respostas
dyorgio

Boa tarde pessoal :slight_smile:
seguindo o costume
vou fazer uma pergunta aqui para entrar na série : “Perguntas sem resposta”
mais , atenção, quando falo isso não é porque ninguem tentou responder…e sim porque ninguem sabe :slight_smile:
A pergunta de 1 milhão de dolares é :

Como pegar o Object do stack em uma Thread no Java?

por exemplo, eu em determinado metodo do meu programa, quero o Object que chamou
esse metodo. com getStackTrace() não temos essa informação, da apenas de saber a classe…
e esse método cai num native no final das contas. :-(.

Objetivo, identificar e recuperar o Object de determinada classe que chamou o metodo, indiferente do tamanho do stack.

Bem, era isso :-).
implementações JNA são bem vindas.

16 Respostas

fabiofalci

AOP não é uma opção?

T

Se o método for um método normal (sem ser estático), basta usar “this”. Certo?

dyorgio

fabiofalci
AOP não resolve por que quero fazer isso independente de estilo de programação cara…
tipo, algo para usar em qualquer programa.pronto ou não.

thingol
resolveria se eu quisesse pegar o objetc do topo do stack (método atual)
mais eu quero varrer o stack atras de um determinado object (classe que estou procurando).

por exemplo:
Obj1.metodo1
–> chama Obj2.metodo2
–> chama Obj3.metodo3
Aqui eu queria poder ter o Obj1…dinamicamente, sem ter que passar por parametro,
pois seria pra funcionar em qualquer clase ja feita ou que será feita.

muito complicado explicar essa coisa :stuck_out_tongue:

dyorgio

Só pra reforçar…
hoje, com o uso e analise do getStackTRace da thread.currentThread
eu consigo saber a classe…
mais a instancia dela no stack não.

estou começando a achar que isso não esta implementado
por causa dos métodos static…mais ai poderia ser null o retorno
do método que obtivesse esse valor…né?

:smiley:

fabiofalci

Por curiosidade, o que vc quer resolver com isso?

dyorgio

Eu tenho um pré-Genesis que estou fazendo, e pretendo fazer ele Opensource ai
pro pessoal do Java. eu iria descobrir a View ( ? extends Component)
que chamou o método com base na minha MVCUnit (estrutura interna do framework para
gerenciamento de unidades MVC, que cuida dos binds) que por fim é quem executa as actions…
simples assim :stuck_out_tongue:

fabiofalci

É swingão então?

Não sei se entendi bem o que vc quer, mas usamos o struts2/xwork para fazer o controle MVC de alguns
sisteminhas swing e o bind ocorre no interceptor. Lá está configurado qual tela sofre o bind.

dyorgio

vou dar um exemplo de uso no meu framework.

tenho uma View que esta sendo instanciada pelo Framework( Sim, dou uma de spring e gerencio minhas instancias dentro do framework), vamos chamala de viewNOVA.
o que eu quero descobrir, é qual View (vamos chamar de viewVELHA)chamou essa minha viewNOVA (se existir alguma).
fica meio complicado de falar de um framework caseiro,
com a pergunta do tópico eu conseguiria fazer isso…
pois saberia a MVUnit que executou a action que por sua vez requisitou a viewNOVA.
e dentro dessa MVCUnit eu tenho a instancia da minha ViewVELHA.

aaaaaaaaaaa.

o que custava o Java ter Thread.getStack() ao invés de Thread.getStackTrace()?!?!?

fabiofalci

Vc quer fazer algo como um refresh na viewVELHA?
Pois é, não chegamos a uma solução mágica para isso, mas sim a uma action com um result específico para aquela
situação que faz o refresh. Mas isto tem que ser previsto dai.

dyorgio

Cara, eu vou te falar o objetivo…mais tu não ri de mim ta?
Quero passar a viewVelha como owner da viewNOVA.
mais como não faço a minima ideia se a action que a viewVELHA
esta executando vai criar ou não uma nova View…não posso passar ela como parametro…
até porque , estou fugindo, e até agora conseguindo essa façanha, do Controller enxergar a view.

lucamartins

Opa!

Cara, se você usar um singleton não resolve?

Acho que fica meio “miau” tentar resgatar a instancia da classe via o stack.

Esta aplicação é web ou desktop?

Ah, ia me esquecendo. Tem como vc pegar a stack correta sim.
Este codigo abaixo é um metodo de uma classe de controle. Ela analisa o stack e desconsidera todos os metodos que são da classe de controle. Dentro deste metodo, eu acho a ultima chamada dentro da classe de controle, então, a chamada seguinte é da classe que a invocou.

O objeto listaMetodos é populado da seguinte maneira:

listaMetodos = new ArrayList<String>();
        Method[] metodos = SuaClasse.class.getMethods();

        for( int i = 0; i < metodos.length; i++ )
            if( ( metodos[i].getName().startsWith("print") || 
                    metodos[i].getName().indexOf("formatar") > -1
                )&&
                !listaMetodos.contains( metodos[i].getName() )
               ){
                listaMetodos.add( metodos[i].getName() );
            }

No meu caso, eu só desconsidero os metodos que tem a “print” em qualquer lugar do nome do metodo.

/**
     * Analisa o Stack e retorna o próximo Stack desconciderando as chamadas 
     * dentro do metodo {@link #printf(String frm, boolean b) printf() }
     */
    private StackTraceElement getNextAvaibleStack( StackTraceElement stacks[] ){
        StackTraceElement avaible = null;
        for( StackTraceElement stack : stacks ){
            if( 
                listaMetodos.contains( stack.getMethodName() ) &&
                stack.getClassName().equals( getClass().getName() )
               ){
                //Se achou, o Stack esta no nível de chamada desta classe,
                //mas para o usuário, apenas as chamadas da classe dele interessam.
                avaible = stack;
            }else if( avaible != null ){
                //Após achar as chamadas dessa classe, a próxima chamada
                //é a do código do úsuario.
                return stack;
            }
        }
        //Não conseguiu analisar o Stack.
        return null;
    }
dyorgio

Oi cara,
olha, esse teu metodo apenas trabalha com o StackTrace ( que eh um objeto que contem algumas info do stack)
se ele trabalhasse como stack , eu teria as instancias que tanto procuro :frowning:
acabei resolvendo o meu problema com metodos utilitarios para
pegar a View de minhas unidades MVC, porem tive como efeito colateral
a amaração de uma unidade mvc com outra, já que preciso passar
para esse metodo utilitario qual a view que quero…
isso tambem eh POG
o unico jeito de não ser POG seria ter acesso as instancias que fazem parte do stack
mais isso em Java parece não existir
talvez com algum hack nativo na VM…:expressionless:
de qualquer maneira deve ter um bom motivo para isso…os caras da Sun sabem, eu não… ;(
a pergunta desse tópico fica continua sem resposta.
eu realmente não esperava resolver o meu problema dessa maneira.
abri esse tópico mais para discutir o porque que esse acesso não esta implementado no JDK…
e se esta, porque ta tão escondido assim?!?!?

jeancz

Cara, realmente não entendo porque você precisa disso. Poderia clarificar melhor nos posts?

ViniGodoy

É, talvez haja uma solução mais elegante se você explicar que problema você está tentando resolver…

dyorgio

O que eu preciso é o seguinte:

Pegar qual Objeto chamou determinado método.

com as seguintes restrições:

  1. Não posso passar ele como parametro.
  2. não posso definir uma regra de execução (AOP - tamanho do stack variavel)

Ao meu ver, consigo fazer isso se existisse getStack() no Thread.
lembrando que: stack não eh a mesma coisa que stackTrace(Trace vem de informações)

Eu tb fiquei desconfiado…como é que Java não tem isso!!!

mais até agora ninguem encontrou um jeito.

isso é muito util para quem faz framework…muito util mesmo :slight_smile:

Como falei, meu problema eu contornei ligando
uma unidade Mvc com outra ( uso o nome das unidades para fazer a ligação)
foi a maneira mais elegante que encontrei…
mais gostaria de desviar a atenção do pessoal para a discussão da pergunta do tópico…
pois acho isso mais relevante :wink:

Agradeço a todos que me deram dicas,
e vamos ver se alguem descobre como ter acesso aos objetos do stack ( null no caso de static).

dyorgio

Sim, cheguei ao fundo do poço…
.mais como é no fundo do poço que as vezes se encontram as melhores soluções
eis que durante uma maratona de filmes do Mr. Bean,
eu encontrei uma solução :slight_smile:
instrumentacão de código…

sim meus amigos, o fundo do poço :stuck_out_tongue:

Eu ja tive experiencias muito boas com o javassist.
Bem, chega de lero-lero
es o código que deve ser gerado dinamicamente para POGear a instancia dos meus objetos
em um Pseudo-Stack feito na unha :slight_smile:

no inicio do body…

try{
    MeuGerenciadorDeStack.add(Thread.currentThread(),this);
    // o resto da implementação aqui...

Explicando…Adiciona o objeto atual do stack no gerenciadorDeStack, passando como chave a Thread atual

no final do body

}finally{
    MeuGerenciadorDeStack.remove(Thread.currentThread(),this);
}

Explicando… faz a limpeza…

Bem, é isso, POG, mais POG com classe :smiley: :wink:

A unica desvantagem que encontrei
seria de ter mais processamento por causa da compilação em runtime.

para metodos static poderiamos colocar null, ou um objeto especifico para esses casos, até mesmo o StackTraceElement…
Opniões please :slight_smile:

Criado 29 de julho de 2009
Ultima resposta 2 de ago. de 2009
Respostas 16
Participantes 6