プログラマメモ2 - programmer no memo2

[java][javassist]privateなメソッドにアクセスするもうひとつの方法 2006/07/19
2006/11/26

javassistを利用して、privateなメソッドにアクセスするもうひとつの方法です。



シナリオ:

下記のクラスのprivateなメソッドgetSにアクセスしたいとします。



public class A_A {



private String s = "hello";



private String getS(){

System.out.println("i am privte method!!");

return s;

}



}





方法は、javassistを利用して、メソッドを取得して、そのメソッドをクラスから削除して、アクセス修飾子を変更して、再度クラスにそのメソッドをaddするというまどろっこしい方法をとっています。





import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;



import javassist.CannotCompileException;

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

import javassist.NotFoundException;

import javassist.bytecode.AccessFlag;



public class TestAccessPrivateMethod2 {



public static void main(String[] args) throws NotFoundException,

CannotCompileException, InstantiationException,

IllegalAccessException, SecurityException, NoSuchMethodException,

IllegalArgumentException, InvocationTargetException, IOException {



ClassPool pool = ClassPool.getDefault();



CtClass myCtClass = pool.get("A_A");

CtMethod ctMethod = myCtClass.getDeclaredMethod("getS");



// 既にあるメソッドを削除

myCtClass.removeMethod(ctMethod);



// アクセス修飾子をpublicに変更

ctMethod.getMethodInfo2().setAccessFlags(AccessFlag.PUBLIC);



// 修正したメソッドを追加

myCtClass.addMethod(ctMethod);



Class myClass = myCtClass.toClass();

Object my = myClass.newInstance();



// 何もしなかったら通常 Exception in thread "main" java.lang.NoSuchMethodException: A_A.getS()

Method exeMth = myClass.getMethod("getS", new Class[] {});

System.out.println(exeMth.invoke(my, new Object[] {}));



}

}

: