삽질하다가 전혀 엉뚱한것을 발견(?) ^^;
그놈의 정체는 JPDA(Java Platform Debugger Architecture)
http://java.sun.com/javase/technologies/core/toolsapis/jpda/
이클립스의 디버그 모드는 가끔 사용하기는 하지만, 이게 API로 제공되고 있을줄이야... ^^;
com.sun.jdi 패키지인데, tools.jar에 포함되어 있다.
본론(?)으로 돌아가서, Javarebel은 어떻게 돌아가는지 파악하는데 또다시 실패했으나, Instrumentation의 redefineClasses() 메소드를 이용해서, 아주 간단하게 클래스를 변경하는 방법을 테스트해본것에 대해서 만족을..... ^^;
여러가지 제약사항이 존재하기는 하나, 추가/수정은 잘 되는거 같음. 아래는 Javassist(http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html)를 이용해서 간단히 메소드 변경을 해본것.
그놈의 정체는 JPDA(Java Platform Debugger Architecture)
http://java.sun.com/javase/technologies/core/toolsapis/jpda/
이클립스의 디버그 모드는 가끔 사용하기는 하지만, 이게 API로 제공되고 있을줄이야... ^^;
com.sun.jdi 패키지인데, tools.jar에 포함되어 있다.
본론(?)으로 돌아가서, Javarebel은 어떻게 돌아가는지 파악하는데 또다시 실패했으나, Instrumentation의 redefineClasses() 메소드를 이용해서, 아주 간단하게 클래스를 변경하는 방법을 테스트해본것에 대해서 만족을..... ^^;
여러가지 제약사항이 존재하기는 하나, 추가/수정은 잘 되는거 같음. 아래는 Javassist(http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html)를 이용해서 간단히 메소드 변경을 해본것.
package kr.kangwoo.test;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
public class MyPreLoader implements ClassFileTransformer, Runnable {
public final Instrumentation instrumentation;
public MyPreLoader(Instrumentation instrumentation) {
this.instrumentation = instrumentation;
}
public static void premain(String agentArgument, Instrumentation instrumentation) {
System.out.println("premain");
MyPreLoader l = new MyPreLoader(instrumentation);
instrumentation.addTransformer(l);
Thread t = new Thread(l);
t.start();
}
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
System.out.println("transform : " + className);
return classfileBuffer;
}
public void hello() {
System.out.println("안녕하세요");
}
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1 * 1000);
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("kr.kangwoo.test.MyPreLoader");
cc.defrost();
CtMethod m = cc.getDeclaredMethod("hello");
m.setBody("{ System.out.println(\"오~! 변한다~ : " + i + "번째\"); }");
ClassDefinition[] cd = new ClassDefinition[1];
cd[0] = new ClassDefinition(MyPreLoader.class, cc.toBytecode());
instrumentation.redefineClasses(cd);
} catch (Exception e) {
e.printStackTrace();
}
hello();
}
}
}