런타임시 Javassist 3.20.0-GA를 사용하여 사용자 정의 Java 에이전트를 통해 바이트 코드를 다시 작성하는 Java 8 프로젝트가 있습니다. 목표는 메소드를 인스트루먼트하여 원래의 본문이 print 문을 사용하여 try/finally 블록으로 래핑되도록하는 것입니다.Javassist를 사용하여 원래의 메서드 로직을 래핑하는 try/finally 로직을 삽입하십시오.
CtClass ctClass = ClassPool.getDefault().get("com.example.test.TimeService");
CtMethod ctMethod = ctClass.getDeclaredMethod("getCurrentTime");
ctMethod.insertBefore("System.out.println(\"Start\");");
ctMethod.insertAfter("System.out.println(\"Stop\");", true);
:
public class TimeService {
public long getCurrentTime(){
try {
System.out.println("Start");
// BEGIN original code
long time = 0;
try {
time = System.currentTimeMillis();
}
catch(Throwable t){
time = -1;
}
System.out.println("The current time is "+time);
return time;
// END original code
}
finally {
System.out.println("Stop");
}
}
}
먼저 나는 다음과 같은 코드를 시도 : 나는 (의견 없음) 출력 다음 수정 된 코드를 싶습니다
public class TimeService {
public long getCurrentTime(){
long time = 0;
try {
time = System.currentTimeMillis();
}
catch(Throwable t){
time = -1;
}
System.out.println("The current time is "+time);
return time;
}
}
: 예를 들어,이 사소한 방법을 제공
이것은 기존의 try/catch/finally 블록을 사용하지 않고 간단한 void 메소드에서 잘 작동하는 것처럼 보였으 나, getCurrentTime() 메소드의 출력은 str 오류가없는 경우
이public long getCurrentTime() {
boolean var10 = false;
long var10000;
long var5;
try {
var10 = true;
System.out.println("Start");
long time = 0L;
try {
time = System.currentTimeMillis();
} catch (Throwable var11) {
time = -1L;
}
System.out.println("The current time is " + time);
var10000 = time;
var10 = false;
} finally {
if(var10) {
var5 = 0L;
System.out.println("Stop");
}
}
var5 = var10000;
System.out.println("Stop");
return var5;
}
위의 코드는 "작동"하지만 에 System.currentTimeMillis 척 : 플랜지 및 에서 System.out.println ("정지") 문은 두 번반복()는 예외를 throw, 다음 var10는 thusly 히 에서 System.out.println ("정지") 문이 두 번실행됩니다를 거짓로 설정 될 않을 것입니다. 부울 플래그를 세이프 가드로 사용하면 여기서는 잘 작동하지 않으므로 메서드의 맨 처음과 끝에 간단히 try/finally를 삽입하는 것이 좋습니다. 많은 시도를 통해 출력물을 여러 번 "정지"
CtClass ctClass = ClassPool.getDefault().get("com.example.test.TimeService");
CtMethod ctMethod = ctClass.getDeclaredMethod("getCurrentTime");
ctMethod.instrument(new ExprEditor(){
public void edit(MethodCall m) throws CannotCompileException {
String start = "{ System.out.println(\"Start\"); }";
String stop = "{ System.out.println(\"Stop\"); }";
m.replace("{ try {"+start+" $_ = $proceed($$); } finally { "+stop+" } }");
}
});
그러나 그것은 "시작" 및 반복 왜곡 된 엉망으로 전환 :
다음 나는 인스트루먼트와 같은 직접 방법을 교체 시도/catch/finally 블록 (너무 지저분 해 여기에 붙여 넣기).
다음에 시도 할 내용이 확실하지 않거나 Javassist API의 잘못된 부분을 사용하고 있는지 잘 모르겠습니다. 그것은 매우 직설적이어야하고 단순한 void 메쏘드와 같이 보인다. 그러나 값이 반환 될 때, 특히 pre/try/catch/finally 블록과 결합하여 결과가 예측할 수 없게된다.
어떤 생각이나 해결 방법이 있습니까?
미리 감사드립니다.
생성 된 코드를 다시 검사했는데 정확합니다. 생성 된 코드가 원본의 배수가 아니 었으면 좋겠다. (10 개 라인이 100 개 라인을 넘는 것을 본 적이있다.) 그렇다면 다시 _ 생성 된 것은 꽤 이상합니다. – user1661467