blog

Javassistによる非侵襲的ログ・インジェクションの実装

最近、会社のプロジェクトのニーズにより、Redissonの再パッケージ化、同時に監視プラットフォームに公開されるログとアラーム監視情報のパッケージ化の必要性が出てきました。しかし、より多くのメソッドの...

Aug 21, 2020 · 5 min. read
シェア

序文

実装プロセス

private static void injectCode(StringBuffer body, String methodName /*元のメソッドのコード*/, boolean returnVoid,CtMethod mold) throws NotFoundException {
 String type = mold.getReturnType().getName();
 body.append("{ int res = 7;
");
 body.append(" long start = System.currentTimeMillis();
" +
 " long cost = -1;
" +
 " long end = start;
" +
 " boolean isSuccess = true;
" +
 " System.out.println(System.currentTimeMillis()); 
" );
 if (!type.equals("void")){
 if (type.equals("boolean")){
 body.append(type + " result = false;
");
 }
 else if (type.equals("String")){
 body.append(type + " result = null;
");
 }
 else if (type.equals("long")){
 body.append(type + " result = 0;
");
 }
 else if (type.equals("int")){
 body.append(type + " result = 0;
");
 }
 else{
 body.append(type + " result = null;
");
 }
 }
 body.append("
 try{" + "
");
 // method()と同様に、元のコードを呼び出す。;(?)クラス・ローダーのすべてのパラメーターは
 if (!"void".equals(type)){
 body.append("result = ");
 }
 body.append(methodName + "(?);
");
 body.append("}catch (Exception e){
" +
 " e.printStackTrace();" +
 " }finally {
" +
 " end = System.currentTimeMillis();
" +
 " cost = start - end;
" +
 " System.out.println(res + );"+
 " }");
 if (!"void".equals(type)){
 body.append("return result;
");
 }
 body.append("}");
 }

バイトコード置換

 private static void addLog(String methodName,CtClass ctClass) throws CannotCompileException, NotFoundException, IllegalAccessException, InstantiationException {
 CtMethod mold = ctClass.getDeclaredMethod(methodName);
 // 元のメソッド名を修正する
 String newName = methodName + "$impl";
 mold.setName(newName);
 //新しいメソッドを作り、元のメソッドをコピーする
 // メインのインジェクション・コード
 CtMethod mnew = CtNewMethod.copy(mold, methodName, ctClass, null);
 StringBuffer body = new StringBuffer();
 try {
 injectCode(body,newName,mold.getReturnType() == CtClass.voidType,mold);
 }catch (Exception e){
 e.printStackTrace();
 }
 // 新しいメソッド
 mnew.setBody(body.toString());
 // 新しいメソッドを追加する
 ctClass.addMethod(mnew);
 }
public class MyClassLoader extends ClassLoader{
 private String path;
 public MyClassLoader(String clazzPath){
 this.path = clazzPath;
 }
 @Override
 protected Class<?> findClass(String name) throws ClassNotFoundException {
 Class log = null;
 byte[] bytes = gatDate();
 if (bytes != null){
 log = defineClass(name,bytes,0,bytes.length);
 }
 return log;
 }
 private byte[] gatDate(){
 File file = new File(path);
 if (file.exists()){
 FileInputStream inputStream = null;
 ByteArrayOutputStream outputStream = null;
 try{
 inputStream = new FileInputStream(file);
 outputStream = new ByteArrayOutputStream();
 byte[] buffer = new byte;
 int size = 0;
 while ((size = inputStream.read(buffer)) != -1){
 outputStream.write(buffer,0,size);
 }
 }catch (Exception e){
 e.printStackTrace();
 }finally {
 try {
 inputStream.close();
 outputStream.close();
 }catch (Exception e){
 e.printStackTrace();
 }
 }
 return outputStream.toByteArray();
 }else{
 return null;
 }
 }
}

次のステップでは、具体的なビジネスについて、ニーズに応じて判断します。

 //  
 ClassPool pool = ClassPool.getDefault();
 CtClass ctClass = pool.get("redisson.RedissonTool");
 List<String> methodList = new ArrayList<>();
 URL path = Thread.currentThread().getContextClassLoader ().getResource("");
 MyClassLoader loader = new MyClassLoader(path.getPath() + "redisson/RedissonTool.class");
 Class<?>redissonTool = null;
 try {
 redissonTool = loader.findClass("redisson.RedissonTool");
 System.out.println(redissonTool.getClassLoader() + "");
 redissonTool.newInstance();
 }catch (Exception e){
 e.printStackTrace();
 }
 Method[] methods = redissonTool.getMethods();
 excludeObjectMethod(methods);
 for (Method i : methods){
 if (i != null){
 addLog(i.getName(),ctClass);
 }
 }
// addLog("set",ctClass);
 RedissonTool redissonTool1 = (RedissonTool) ctClass.toClass().newInstance();
Read next

モバイル - orientationchangeイベント

今日、改めてプロジェクトを見てみると、ウィンドウのリスニング・イベントreziseで、コールバック関数がremの計算をリフレッシュするために使われていることがわかりました。これを見た後、なぜremの計算に追加する必要があるのか戸惑い、関連情報を調べてみると.

Aug 21, 2020 · 1 min read