首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Javassist添加语句

使用Javassist添加语句
EN

Stack Overflow用户
提问于 2015-06-19 05:15:09
回答 1查看 1.2K关注 0票数 2
代码语言:javascript
复制
System.out.println("A read operation on a field is encountered "); 

当在非本地字段上执行读取操作时,我如何添加语句(例如,上面的语句)?此外,我还需要知道所读取字段的详细信息,并且这组细节应该对应于字段的唯一性。

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

代码语言:javascript
复制
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);
   }

}

用户类测试是:

代码语言:javascript
复制
class test{
  public static void main(String[] args){
    Greet g("SPANISH");
    g.showCount();

  }

}

在上面的示例中,在使用javassist之后,我们的代码应该输出:

代码语言:javascript
复制
A read operation on a field is encountered
1
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-07-01 14:23:53

你可以通过使用ExprEditor来做你想做的事情。ExprEditor允许您编辑FieldAccess中所做的工作,要实现您的请求,您可以创建一个注入器,执行以下操作:

代码语言:javascript
复制
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/

上述所有锅炉板的兴趣线如下:

{ System.out.println(\"A read operation on a field is encountered \"); $_ = $proceed($$); }

这里发生了什么事?

  • 首先要注意的是,所有的代码都在花括号中,如果您知道自己在javassist中使用的方法,这对您来说是微不足道的,如果不是,它可能会让您花几分钟时间试图了解出了什么问题。
  • 那么你就有了你想要的System.out
  • 最后,您有了一条神奇的主线:$_ = $proceed($$);。您可以在Javassi协助教程中找到有关这方面的更多信息(在该部分中搜索FieldAccess,因为它们没有直接的锚点,对不起!)但基本上这一行的意思是,字段访问的结果值是为字段访问调用的虚拟方法的值,换句话说,是字段的实际值。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30930400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档