Auflösung von Abhängigkeiten unter Verwendung des Proxy-Mechanismus in Java

Description

  • Auflösung von Abhängigkeiten nach Instantiierung unter Nutzung des Java Proxy-Mechanismus

    • Reihenfolge in Prozess: Instrumentierung -> Instantiierung -> Abhängigkeitsauflösung -> Ausführung

    • Wird ein Poxy für Dpcy im Beispiel erstellt und im Testtreiber eingehängt gibt es einen Konflikt, da der Classloader von ByCounter und derjenige der Proxyklasse, bzw. den darin verwendeten Klassen, ein anderer ist. Klassengleichheit wird damit nicht mehr korrekt erkannt.

Beispiel (noch ohne Proxy-Mechanismus, nur zur Veranschaulichung von Abhängigkeiten):
class Dpcy {
void calculate() {
System.out.println("Dpc.calculate");
}
}
class DependencyIssue {
Dpcy dep;

void setDependency(Dpcy dep) {
this.dep = dep;
}

// This Method should be measured using ByCounter
void doSomething() {
dep.calculate();
}
}

Environment

Operating System: All
Platform: PC

Activity

Show:
Former user
June 24, 2012, 6:33 PM

Typ-Gleichheit wird in Java über zwei Merkmale geprüft:

  1. qualifizierter Klassen-/Interfacename

  2. id des ClassLoader mit dem die Klasse/das Interface geladen wurde.

Daher spielt Typ-Kompatibilität zunächst keine Rolle.

Die Verwendung eines Interfaces zum Zugriff ist dennoch eine funktionierende Lösung. ByCounter ist jetzt so angepasst, dass der verwendete ClassLoader (intern wird ein Javassist ClassLoader) Interfaces nie selber lädt, sondern an den Standard-Java-ClassLoader weiterreicht. Da Interfaces nicht instrumentierbar sind (da sie keinen Code enthalten), funkioniert das immer. Damit lassen sich jetzt instrumentierte Klassen mit dem "normalen" Interface nutzen.

Die gezieltere Mischung von mit ByCounter und ohne ByCounter geladenen Klassen ist aber weiterhin schwierig. Das liegt unter anderem daran, dass beim Laden von Klassen auch Abhängigkeiten geladen werden. Definiert eine Klasse A zum Beispiel eine Methode mit Parameter vom Typ B, so wird beim Laden von A auch B geladen. Dadurch gibt es einen Konflikt wenn zu einem späteren Zeitpunkt B instrumentiert verwendet wird (Ungleichheit der ClassLoader).

Umgehen ließe sich dieses Problem, indem man den System-ClassLoader (

) mit dem ClassLoader von ByCounter ersetzt. Der System-ClassLoader lässt sich in der Kommandozeile über die Option

setzen. Das ist aber offensichtlich nicht in allen Fällen möglich und funktionierte in einem kurzen Test von mir leider noch nicht (Klassen wurden nicht gefunden etc.; weitere Anpassungen sind wahrscheinlich notwendig).

User known
July 29, 2011, 4:12 PM

Der Type-Cast zwischen instrumentierter und uninstrumentierter Klasse sollte aus meiner Sicht in keinem Fall gefährdet sein, da lediglich eine andere Implementierung hinter der identischen Schnittstelle verwendet wird.

Die Verwendung von BytecodeCounter.execute(...) schließt die Auflösung von Abhängigkeiten (Bspw. via Proxy-Instanzen oder Stubs) nicht mit ein. Wie lassen sich diese Abhängigkeiten kompatibel mit BytecodeCounter auflösen? Funktioniert dies auch wenn BytecodeCounter, der Code zum Abhängigkeiten Auflösen/Testen und die zu testende Klasseninstanz in jeweils unterschiedlichen Plug-ins liegen?

User known
July 29, 2011, 3:29 PM

Das Problem, dass der Code jetzt hervorruft ist folgendes:
Hier wird manuell die mit ByCounter instrumentierte Klasse aus ByCounter geholt und dann zusammen mit den uninstrumentierten Klassen verwendet. Da instrumentierte Klasse != uninstrumentierte Klasse funktioniert natürlich auch das casting nicht.
Aus diesem Grund ist auch der normale Weg ByCounter zu benutzen, den gesamten Code der die instrumentierte Klasse verwenden mit BytecodeCounter.execute() anzustoßen. Dies bewirkt, dass der ByCounter-Classloader verwendet wird und solche Klassenkonflikte nicht auftreten. Anders lässt sich das m.M.n. nicht vermeiden.
Das habe ich nicht bedacht als du BytecodeCounter.instantiate explizit verfügbar gemacht hast. Ich überlege im Moment ob es für BytecodeCounter.instantiate angesichts dieser Einschränkungen überhaupt eine Berechtigung gibt.

User known
July 20, 2011, 5:59 PM

(In reply to comment #1)
Das Beispiel ist angepasst und zeigt den Fehler, der bei Benutzung der BytecodeCounter API entsteht, zuverlässig auf.

User known
July 20, 2011, 2:44 PM

Das Beispiel habe ich in einen Testcase ausgebaut (in der Klasse de.uka.ipd.sdq.ByCounter.test.TestProxyClasses). Das genaue Problem kann ich an dem Beispiel leider noch nicht erkennen. Vielleicht kannst du dir das mal ansehen/anpassen, um das Problem mit der Klassengleichheit hervorzurufen.

Fixed

Assignee

Former user

Reporter

Henning Groenda

External issue URL