In einer großen Anzahl von Klassen, die von der gemeinsamen Vorfahrenklasse abgeleitet sind, habe ich die Methode something()
deren Verhalten ich ändern möchte, um die Ausführungszeit zu messen. definiere ich zwei weitere Methoden in der gemeinsamen Vorfahren KlasseJavassist: Kopiermethode mit Debug-Informationen?
// in the common ancestor class:
// this method is defined in all derived classes
public void something() {
System.out.println("something{");
System.out.println("something}");
}
// the body of this method will replace the body of something()
public void measuredSomething() {
System.out.println("measuredSomething{");
roomForSomething();
System.out.println("measuredSomething}");
}
// the body of this method will be replaced by the body of something()
public void roomForSomething() {
// this code will be replaced with something else
System.out.println("roomForSomething{");
System.out.println("roomForSomething}");
}
Und ich tue das Ersetzen mit Javassist:
// someClass is known
String superClassName = someClass.getName();
String className = superClassName + "__proxy";
CtClass ctSuperClass = ClassPool.getDefault().get(superClassName);
CtClass ctClass = ClassPool.getDefault().makeClass(className);
ctClass.setSuperclass(ctSuperClass);
// roomForSomething := something
CtMethod methodSomething = ctSuperClass.getMethod("something", "()V");
CtMethod methodSomething2 = CtNewMethod.copy(methodSomething, "roomForSomething", ctClass, null);
ctClass.addMethod(methodSomething2);
// something := measuredSomething
// (and measuredSomething() will call roomForSomething())
CtMethod methodMeasuredSomething = ctSuperClass.getMethod("measuredSomething", "()V");
CtMethod methodMeasuredSomething2 = CtNewMethod.copy(methodMeasuredSomething, "something", ctClass, null);
ctClass.addMethod(methodMeasuredSomething2);
someClass = ctClass.toClass();
result = someClass.newInstance();
Und es funktioniert. Der Debugger kann den ausführenden Code jedoch nicht anzeigen.
Wie kopiere ich die Debugging-Informationen zusammen mit dem Byte-Code, so dass der Debugger die ausführende Quelle anzeigen würde?
(Es ist nicht möglich, wenn der Methodencode modifiziert wird, soll aber in diesem speziellen Fall möglich sein.)
((Ich habe schlug die Methode something()
in zwei Verfahren aufgeteilt, auf die gleiche Art und Weise ., da es Thread.run()
außer Kraft zu setzen sind, und Thread.start()
aufzurufen ich bin gebeten worden, eine solche Änderung zu vermeiden))
UPDATE
Die folgende Methode etwas bessere Ergebnisse gibt. t Der Debugger stoppt in der über CtMethod.make()
generierten Funktion nur, wenn er von der aufgerufenen Funktion zurückkehrt; die generierte Funktion ist in der Stack-Trace sichtbar; Die Quelle der generierten Funktion ist nicht verfügbar.
// something := measuredSomething
CtMethod methodSomething = CtMethod.make("public void something() {super.measuredSomething();}", ctClass);
ctClass.addMethod(methodSomething);
// roomForSomething := something
CtMethod methodRoomForSomething = CtMethod.make("public void roomForSomething() {super.something();}", ctClass);
ctClass.addMethod(methodRoomForSomething);
Es wäre wirklich gut, wenn es möglich wäre, die Quelle der generierten Funktion anzuzeigen.