草庐IT

java - 如何在每次返回之前向消息添加代码?

coder 2024-03-06 原文

我目前正在尝试通过精心制作的 java-asm 库(版本 4)生成代码。 更具体地说,我想将代码附加到方法的末尾,就在每次返回调用之前。我成功地能够在方法代码之前添加代码。但是目前我不知道如何执行上述转换。我真的很感激关于如何完成这一点的指示。

MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv.visitCode();
mv.visitVarInsn(Opcodes.ALOAD, 42);
return mv;

最佳答案

您有两个解决方案:

<强>1。在MethodVisitor中使用visitInsn(int opcode)方法:

//this is the custom method visitor
private class InsertInitCodeBeforeReturnMethodVisitor extends MethodVisitor{

    public InsertInitCodeBeforeReturnMethodVisitor(MethodVisitor mv) {
        super(Opcodes.ASM4, mv);
    }

    @Override
    public void visitInsn(int opcode) {
        //whenever we find a RETURN, we instert the code, here only crazy example code
        switch(opcode) {
          case Opcodes.IRETURN:
      case Opcodes.FRETURN:
      case Opcodes.ARETURN:
      case Opcodes.LRETURN:
      case Opcodes.DRETURN:
      case Opcodes.RETURN:
              mv.visitVarInsn(Opcodes.ALOAD, 42);
              break;
          default: // do nothing
        }
        super.visitInsn(opcode);
    }
}

<强>2。使用 onMethodExit(int opcode) AdviceAdapter 中的方法在 org.objectweb.asm.commons 中:

//this is the custom method visitor
private class InsertInitCodeBeforeReturnMethodVisitor extends AdviceAdapter{

    public InsertInitCodeBeforeReturnMethodVisitor(MethodVisitor mv, int access, String name, String desc) {
        super(Opcodes.ASM4, mv, access, name, desc);
    }

    @Override
    protected void onMethodExit(int opcode) {
        if(opcode != Opcdoes.ATHROW) {
            mv.visitVarInsn(Opcodes.ALOAD, 42);
        }
    }
}

我个人更喜欢 AdviceAdapter,因为它消除了实际调用原始返回指令的麻烦,就像您必须处理第一个解决方案(例如 super.visitInsn(opcode);) .其次,它为访问 RETURN 指令(和 ATHORW)提供了很好的抽象;对于 Vanilla MethodVisitor 中的 visitInsn(int opcode) 方法而言,这是不正确的,您必须在其中检测对 RETURN 指令的访问许多其他的,例如 DUPICONST_0 等,它们可能与手头的问题相关,也可能不相关。

但这又取决于手头的问题。如果这是唯一正在执行的检测,我将坚持使用 AdviceAdapter。如果您想结合访问 RETURN 指令执行其他操作,我可能会继续使用简单的 MethodVisitor,因为它可能会给我更大的灵 active 。话虽这么说,我已经使用 AdviceAdapter 一年多了,用于一个重型仪器驱动的项目,到目前为止它运行良好!


编辑:

应用方法访问者

通常不清楚如何使用或应用方法访问者/方法适配器(至少对我而言),所以我在这里整理了一个快速代码示例:gist.github.com/VijayKrishna/1ca807c952187a7d8c4d ,它展示了如何通过相应的类访问者/类适配器来使用方法适配器。在示例代码片段中,我更改了我在此答案中使用的方法适配器的名称,但它们做同样的事情。此外,该代码片段还显示了一个扩展 AdviceAdapter 的方法适配器。

总而言之,您首先按如下方式“调用”类适配器:

ClassReader cr = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES);
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className);
cr.accept(returnAdapter, 0);

然后在类适配器的 visitMethod 方法中按照如下方式调整方法:

MethodVisitor mv;
mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv = new MethodReturnAdapter(Opcodes.ASM4, className, access, name, desc, mv);
return mv;

关于java - 如何在每次返回之前向消息添加代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16234286/

有关java - 如何在每次返回之前向消息添加代码?的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  8. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  9. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  10. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

随机推荐