Methodenaufrufe verfolgen



  • Hallo zusammen!

    Weiss einer von Euch ob es möglich ist, in Java Methodenaufrufe von Klassen zu verfolgen?

    Also versteht mich nicht falsch, klar kann man bei einer eigens implementierten Klassen auf relativ simplem Weg dafür sorgen, dass Methodenaufrufe bestimmte Ereignisse auslösen. ( man bräuchte nicht mal EventListener! )
    Was aber, wenn ich die betreffende Klasse nicht selbst implementiert habe, und nur per Reflection ansteuere?
    Ich kann alle nur erdenklichen Informationen über die Klasse erfragen, sie Instanziieren und natürlich auch Methoden ansteuern, alles per Reflection. Nur ich hab keine Möglichkeit auf das Aufrufen einer solchen Methode zu reagieren! Mir fehlt die passende Schnittstelle zu den Klassenmethoden!

    Gibt es irgendeine Möglichkeit die Methodenaufrufe solcher Klassen zu überwachen, ohne den Code neu implementieren zu müssen?

    Danke!

    Grüße,
    TS++



  • Vielleicht kommt man ja über java.lang.reflect.Proxy weiter !?
    Korrigiert mich, wenn ich falsch liege!

    Grüße,
    TS++



  • Für alle die ebenfalls an dem Thema interessiert sind, hier etwas Beispielcode:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener; 
    
    //-------------------------------------------------------------------------------------------------------------------
    
    public class ProxyTip 
    {
        public static void main(String args[]) throws Exception 
        {
            String className = args[0];
            Class c = Class.forName(className);
            InvocationHandler handler = new UniversalHandler();
            Object o = Proxy.newProxyInstance(c.getClassLoader(),new Class[] { c },handler);
    
            if ( className.equals("java.lang.Runnable") ) 
            {
                Thread t = new Thread((Runnable) o);
                t.start();
            }
            else if ( className.equals("Publisher") ) { System.out.println(((Publisher) o).publish()); }
        }
    }
    
    //-------------------------------------------------------------------------------------------------------------------
    
    interface Publisher 
    {
        int publish();
    }
    
    //-------------------------------------------------------------------------------------------------------------------
    
    class UniversalHandler implements InvocationHandler 
    {
        public Object invoke(Object proxy, Method method, Object[] args) 
        {
            try 
            {
                System.out.println("method invoked: " + method);
                Class c = method.getReturnType();
                System.out.println("should return type: " + c);
                if ( c.toString().equals("void") ) return null;
    
                else if ( c.toString().equals("int") )   return new Integer(0);
                else if ( c.toString().equals("float") ) return new Float(0);
                else if ( c.toString().equals("byte") )  return new Byte((byte) 0);
                else if ( c.toString().equals("char") )  return new Character((char) 0);
                else if ( c.toString().equals("short") ) return new Short((short) 0);
                else                                     return c.newInstance();  
            }
            catch (Exception e) 
            {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    Grüße,
    TS++



  • Also es funktioniert !
    Man lässt durch den Proxy zur Laufzeit beliebige Interfaces implementieren, deren Methodenaufrufe dann per 'invoke(...)' den InvocationHandler des Proxys ansteuern und ihm bekanntgeben, welche Methode aufgerufen wurde. Im InvocationHandler muss dann entschieden werden, wie der Methodenaufruf zu verwerten ist (z.B.: Methode per Reflection auf das betreffende Objekt anwenden). Man implementiert also mit dem Proxy eine dynamische Zwischenschicht zwischen den Methodenaufrufen der Endanwenderapplikation und dem eigentlichen Ansteuern der betroffenen Objekte. In dieser Zwischenschicht kann ich jetzt relativ leicht feststellen, wann welche Methode mit welchen Argumenten aufgerufen wird.
    Einzige Grundvoraussetzung, und das könnte den Erfolg etwas schmälern, wäre, dass alle Methodenaufrufe in der Endanwenderapplikation über den Proxy gehen müssen. Ich muss also die zu registrierenden Methoden immer auf das Proxyobjekt anwenden. Von allen anderen Methodenaufrufen kriegt der InvocationHandler nichts mit! 😞 (leider)

    Grüße,
    TS++


Log in to reply