Quem chama? - Há como descobrir qual classe chama determinado método ou função em Java?

Olá,

temos uma classe legada que possui uma série de métodos e funções estáticas que são utilizadas por diversas outras partes do sistema.

Devido a uma necessidade que surgiu, gostariamos de, a partir destes métodos, saber qual classe que os invocou sem alterar sua interface.
Dado que se trata de código legado, gostaríamos de fazer isto sem a utilização de qualquer framework (ou seja, nada de AOP neste caso).
Para tal, acreditamos que precisaremos ter acesso à pilha de execução da aplicação, porém ainda não descobrimos como acessá-la (falha nossa).

Alguém aqui já passou por situação semelhante? Como devemos proceder?
O acesso à pilha de execução impactaria muito negativamente à performance do sistema?

Só através de xunxo, e não há 100% de garantia (embora eu nunca tenha realmente visto falhar):

Basta criar uma exceção, e obter sua strack trace:

Exception e = new Exception(); StackTraceElement[] stack = new e.getStackTrace(); System.out.println("Quem me chamou foi: " + e[1].getClassName + "." + e[1].getMethodName());

Você precisa pegar o índice 1, pq o 0 refere-se a própria função que criou a exception.
Se quiser separar isso num outro método, daí terá que pegar o índice 2.

Era exatamente o que eu queria evitar :slight_smile: Mas valeu de qualquer maneira.
Lendo o código fonte da classe Throwable, encontrei o seguinte comentário:

o que torna este método pouco seguro para a aplicação em questão (ela será executada nos mais variados sistemas operacionais).

Sendo assim, pergunto: será que não há uma solução mais elegante para este problema?
Caso alguém aqui saiba quais as máquinas virtuais que irão apresentar este comportamento, também já ajudaria bastante.

Pode usar aop!

Isso foi sério? Vc sabe realmente como fazer? Tem algum exemplo?
Ou foi um comentário daqueles: “Já ouvi falar que com isso daria?”

Sim, eu usei com AspectWerkz.

Tu pode definir um aspecto para algo assim

@Before("call(@com.mycompany.Annotations * *.*(..)) && this(caller)")
public void intercept(Object caller, JoinPoint jp) throws Throwable {
...

Aquele primeiro parametro, Object caller, é quem chamou!

*editado, li agora que ele nao quer usar AOP pois nao quer mexer nas classes!

[quote=ViniGodoy]Isso foi sério? Vc sabe realmente como fazer? Tem algum exemplo?
Ou foi um comentário daqueles: “Já ouvi falar que com isso daria?”[/quote]

Com o AspectJ isso é possível, é só pegar o “this” atual, não? (claro que isso não vai funcionar pra chamadas via métodos estáticos)

Não vejo outra forma simples (e limpa) de fazer isso que não seja com AOP (ou pior, engenharia de bytecode, enchertando bytecode nas chamadas desse método).

da pra fazer isso em javascript?

Googlando por “javascript caller” achei isto:

vlw

Só pra adicionar…

        // Apenas para DEBUG
        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
        StackTraceElement ee = stacktrace[2];//maybe this number needs to be corrected
        String origem = ee.getClassName() + " > " + ee.getMethodName();

        System.out.println("Quem me chamou? " + origem);
        // Apenas para DEBUG