使用Javassist添加语句 [英] Adding a statement using Javassist

查看:142
本文介绍了使用Javassist添加语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

System.out.println("A read operation on a field is encountered "); 

我怎样才能添加一个语句,比如上面的语句,每当读取时都是
操作是否已在非本地字段上执行?
并且我还需要知道所读取字段的详细信息以及
详细信息的集合应该与字段的唯一性相对应

How can I add a statement, lets say , the above statement , whenever a read operation has been performed on a non-local field ? and also I need to know the details of the field which is read and the set of details should correspond to the uniqueness of the field

示例(删除问题中的抽象):

Example (to remove abstraction in the question):

public class Greet{
   int knowncount;
   public Greet()
   {
      System.out.println("Hello");
      knowncount++;
   }   
   public Greet(String language)
   {
     if(String.equals("ENGLISH"))  {System.out.println("Hello"); knowncount++; }
     else  if(String.equals("SPANISH")) {System.out.println("Hola"); knowncount++;}
     else  System.out.println("Language not recognized");
   }

   public void showCount() 
   {
     System.out.println("count : "+knowncount);
   }

}

,用户类测试是:

class test{
  public static void main(String[] args){
    Greet g("SPANISH");
    g.showCount();

  }

}

以上使用javassist之后的示例我们的代码应输出:

in the above example after using javassist our code should output :

A read operation on a field is encountered
1


推荐答案

您可以使用Javassist的 ExprEditor 。 ExprEditor允许您编辑在 FieldAccess 中完成的操作,要实现您的请求,您可以创建一个执行以下操作的注入器:

You can do what you ask by using Javassist's ExprEditor. ExprEditor allows you to edit what is done in a FieldAccess, to implement your request you can create an injector that does the following:

ClassPool classPool = ClassPool.getDefault();
CtClass greetCtClass = classPool.get(Greet.class.getName());

greetCtClass.instrument(new ExprEditor() {
        @Override
        public void edit(FieldAccess fieldAccess)
                throws CannotCompileException {
            if (fieldAccess.getFieldName().equals("knowncount")) {
                fieldAccess
                        .replace(" { System.out.println(\"A read operation on a field is encountered \"); $_ = $proceed($$); } ");
            }
        }
    });

    greetCtClass
            .writeFile("<ROOT DIRECTORY WHERE THE CLASSES ARE>");

解释参数的最佳方法是举例,想象一下Greet类(碰巧在greatPackage)位于以下路径 /home/user/dev/proj1/build/greetPackage/Greet.class 。在这种情况下,您的根目录将是 / home / user / dev / proj1 / build /

Best way to explain parameter is with an example, imagine that Greet class (that happens to be in the greatPackage) is in the following path /home/user/dev/proj1/build/greetPackage/Greet.class. In this scenario your root directory will be /home/user/dev/proj1/build/.

该行上面所有锅炉板的兴趣如下:

The line of interest in all the boiler plate above is the following:

{System.out.println(\对一个油田的读操作是遇到\); $ _ = $ proceed($$); }

这里发生了什么?


  • 首先注意所有代码在花括号之间,如果你知道你在javassist中的方式这是微不足道的对你而言,如果没有,它会让你在几分钟内试图理解错误。

  • 然后你有你要求的System.out

  • 最后你有魔术线 $ _ = $ proceed($$); 。您可以在 javassist tutorial 中找到有关此内容的更多信息(搜索对于该部分中的FieldAccess,因为它们没有直接的锚点,抱歉!)但基本上该行所说的是,字段访问的结果值是为其调用的虚拟方法的值。字段访问,换句话说就是字段的实际值。

  • First notice that all code is between curly brackets, if you know your way in javassist this is something trivial to you, if not it might make you loose a few minutes trying to understand what is wrong.
  • Then you have the System.out you requested
  • Finally you have a magic line: $_ = $proceed($$);. You can find more information about this in the javassist tutorial (search for FieldAccess in that section, since they don't have a direct anchor for it, sorry!) but basically what this line is saying is that the resulting value of the field access is the the value of the virtual method that's being invoked for the field access, so in other words the actual value of the field.

请记住,你必须重写你的Greet类注入器在一个单独的JVM进程中,之后只有你能够使用带有注入行为的类,除非你做一些带有类加载的技巧以确保加载修改后的版本。我不会涉及这些主题,因为它超出了范围,但如果您需要帮助,请说出来。我很乐意帮助你。

Keep in mind that you have to rewrite your Greet class with the injector in a separated JVM process and only afterwards you'll be able to use the class with the injected behavior, unless you do some tricks with classloading to make sure you load the modified version. I'm not going into those topics because it's out of the scope, but if you need help with that as well please say so. I'll gladly help you out.

这篇关于使用Javassist添加语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆