【问题标题】:Can byte-code manipulation change the return type of a Java method at run-time?字节码操作能否在运行时更改 Java 方法的返回类型?
【发布时间】:2012-11-16 11:38:32
【问题描述】:

我想知道是否可以通过字节码操作来做这样的事情:

public class Foo {
    public int getBlah() {
       return 1;
    }
}

public void hi(int x) {
    System.out.println("hi: " + x);
}

public void hi(String x) {
    System.out.println("wow: " + x);
}

现在我想打电话:

hi(foo.getBlah());

并调用 String 参数的重载 hi 方法。

【问题讨论】:

  • 你到底在做什么?如果它只是关于字符串和整数,你可以解析/转换这些参数和返回类型。您应该尝试陈述您的问题,而不是将自己局限于字节码操作——通常没有必要使用它。
  • 我想在运行时从一种方法转移到另一种方法,即使考虑到我的 getBlah() 方法的返回类型这看起来是不可能的。
  • 你打算使用什么字节码库?而且这很有可能,我以前也做过类似的事情。
  • @Austin 你在开玩笑吧? :) Javassist 或 CGLIB,任你选择。
  • @JohnPristine 开什么玩笑?这些并不是唯一的图书馆。

标签: java proxy javassist cglib bytecode-manipulation


【解决方案1】:

你能处理hi(int x) 上的标记值吗?如果是,你可以这样做:

public void hi(int x) {
    if (x == Integer.MIN_VALUE) {
        String newParam = getTheParamFromProxySomehow();
        hi(newParam);
        return;
    }    
    System.out.println("hi: " + x);
}

基本上是:

  • 通过代理拦截getBlah()方法
  • 保存(在 ThreadLocal? 中)您要传递给重载的 hi 方法的任何字符串参数
  • 返回标记值,例如0-1Integer.MIN_VALUE
  • 做上面的伎俩

它有点hacky,当你没有原语时它看起来最好,所以你可以使用null作为你的标记值。希望有人有更好的答案。 :)

【讨论】:

  • 嗨,欢迎来到 stackoverflow!请注意,您可以使用反引号将代码内联以使其更易于阅读。
【解决方案2】:

即使你可以改变返回类型,也解决不了问题。编译器在编译时决定调用哪个重载方法的实现。更改返回类型不会更改调用的方法。字节码仍会使用String 调用hi(int x) 方法,并且可能会导致错误。

【讨论】:

    【解决方案3】:

    你的问题太笼统了。但是为了发挥您的想象力,请在 ASM 框架的帮助下查看 Java 中的 my old blog about operation overload。下面是一个小例子:

      BigInteger val = Evaluator.evaluate(new Evaluation() {
            public int evaluate(int x, int y) {
              return x - y;
            }
          }, new BigInteger("2"), new BigInteger("3"));
    

    【讨论】:

    • 我只是回答了你的问题。你看过我链接的博文吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2011-11-09
    相关资源
    最近更新 更多