标签: bytecode-manipulation

字节码操纵模式

字节码操作的合法用途是什么以及人们如何在实践中实现基于字节码操作的解决方案?

更新:我应该更清楚地说明这个问题实际上是关于人们使用什么模式和技术来使代码在字节码操作的帮助下飞行.

像已经提到的面向方面编程或动态构建代理对象和类似技术的东西.

java bytecode bytecode-manipulation

7
推荐指数
1
解决办法
2815
查看次数

将编程注释添加到Java类

用法示例:
我想在类字段上添加一个自定义注释@MyContainer,然后在所有这些字段上自动添加相关的Hibernate注释(取决于字段类型和属性).
另外,我需要将JAXB XmlType注释添加到类中,并将类型名称基于类名.
我还希望基于其类型等向字段添加注释.所有添加的注释应该在运行时可用(因此hibernate/JAXB可以找到它们).
我知道以下选项:

  1. 预处理类源(错误选项)
  2. 使用javax.annotation.processing API编译期间的处理
  3. 使用Java Assist等工具进行编译后操作
  4. 使用java.lang.instrument API在类加载期间进行操作
  5. 使用AspectJ(功能不够强大)

我的主要目标是:

  1. 在类和源之间保持同步以进行调试
  2. 支持Maven和IDE(Eclipse/Intellij)的工作

如果已经完成此类工作的人能够为这样的任务推荐最佳方法(也许还有潜在的陷阱),我将不胜感激.

java compiler-construction annotations bytecode-manipulation

7
推荐指数
1
解决办法
1741
查看次数

使用javassist用字节码中的方法替换java运算符

我的目标

为了能够在运行时检测何时进行比较(或任何其他操作,如*, - ,/,>,<,......

应该使用Javassist或ow2 ASM来编辑类的字节码

必须实现的目标

这段代码

public class Test{

    public void m(){

        if(a>2){
        //blablabla         
        }

    }  

}
Run Code Online (Sandbox Code Playgroud)

必须成为

public class Test{

    public void m(){

        if(someExternalClass.greaterThan(a,2)){
            //blalbla           
    }

    }

}
Run Code Online (Sandbox Code Playgroud)

greaterThan将返回与'>'完全相同的结果,但也将用于保存比较量每次进行比较时都会通知外部类

额外的说明

必须在有操作的任何地方进行.所以不仅在if语句中.

这意味着

int a = c+d;
Run Code Online (Sandbox Code Playgroud)

也必须成为

int a = someExternalClass.add(c,d);
Run Code Online (Sandbox Code Playgroud)

您对如何使用Javassist或其他库实现此目的有任何建议吗?

我想它与像IFLT,IFGT这样的OpCodes有关

java bytecode bytecode-manipulation javassist java-bytecode-asm

6
推荐指数
1
解决办法
721
查看次数

将代理附加到现有对象?

我的计划是编写一个基于注释的缓存框架,用于缓存方法的返回值.当第一次使用特定参数调用方法时,缓存应该存储方法返回值.当使用相同的参数第二次调用相同的方法时,该方法应该从缓存返回先前计算的结果,而不是再次执行其代码.我的注释看起来像这样:

@Cached(cacheProvider = HashMapCacheProvider.class)
public Product getProduct(String productId){    
    // Scraping the product from a website ...
    return product;
}
Run Code Online (Sandbox Code Playgroud)

目前我的小框架工作已经很好了.我正在使用Javassist创建包含带注释方法的类的代理对象.为了创建一个新的缓存对象,我正在使用此代码:

public static <T> T newCachedInstance(Class<T> clazz)
    throws InstantiationException, IllegalAccessException {

    ProxyFactory factory = new ProxyFactory();
    factory.setSuperclass(clazz);
    factory.setFilter(new MethodFilter() {
        public boolean isHandled(Method m) {
            // ignore finalize()
            return !m.getName().equals("finalize");
        }
    });

    Class<T> c = factory.createClass();

    T proxy = c.newInstance();
    ((ProxyObject) proxy).setHandler(new CachedMethodHandler());
    return proxy;
}
Run Code Online (Sandbox Code Playgroud)

问题是,我可以通过此方法创建新的缓存对象,而不是通过其类的构造函数创建.因此,我正在寻找一种解决方案,将已有的对象附加到缓存机制.

这是我的问题:是否可以将代理附加到现有对象?根据我的理解,如果不更新对该对象的所有现有引用,这是不可能的.

我的另一种方法是使用字节码操作来操纵带注释的方法的代码,如下所示:

public class Hello {
    public void say() {
         System.out.println("Hello");
    }
}

public …
Run Code Online (Sandbox Code Playgroud)

java proxy bytecode-manipulation javassist

6
推荐指数
1
解决办法
1687
查看次数

字节码操作是否安全

使用像javaassist这样的API执行字节码操作,在编译后修改类文件.但是,如果优化了java代码,那么修改是否可以在错误的地方执行?有办法避免这个问题吗?常规Java和Android之间的故事有何不同?

java android bytecode-manipulation javassist java-bytecode-asm

6
推荐指数
1
解决办法
363
查看次数

使用ASM读取方法调用参数

当访问方法指令a.doAnother(account.getId);使用visitMethodInsn()ASM.我需要从方法参数获取帐户account.getId()类型,帐户类型是Account.但是我得到的返回类型account.getId()long.如何获得Account此处的帐户类型?

java bytecode-manipulation java-bytecode-asm

6
推荐指数
0
解决办法
168
查看次数

Dalvik Verifier中的参考与精确参考

我正在Dalvik字节码上编写工具,该代码对各种方法调用条目执行一些日志记录。具体来说,在各种方法调用站点,我将插入一组指令,这些指令收集参数,将其放入Object[]数组中,然后将其传递给日志记录函数。

这一切都很好,很好,我已经实现并克服了大多数应用程序的所有麻烦。但是我遇到了一个特别难以理解的Dalvik验证程序错误:

java.lang.VerifyError: Verifier rejected class io.a.a.g: void io.a.a.g.r() 
failed to verify: void io.a.a.g.r(): [0x570] register v5 has type Reference: 
java.lang.Object but expected Precise Reference: java.lang.String
Run Code Online (Sandbox Code Playgroud)

我查看了仪器生成的代码,我所做的只是将寄存器v5放入对象数组中。

我在这里有几个问题:

  • 什么是精确参考,为什么它与参考不兼容?
  • 这里的偏移量是什么意思?[0x570]指向字节码指令的中间,因此不会清楚地映射到任何指令:那里的指令不涉及v5
  • 我将如何调试呢?理想情况下,我想知道验证者认为应该发生的情况并加以解决。

编辑:

这是我正在谈论的方法的字节码的转储。https://gist.github.com/kmicinski/c8382f0521b19643bb24379d91c47d36正如你所看到的,0x570不是指令的开始,(据我可以告诉)没有任何地方有一个字符串,其中R5冲突它应该是一个对象。

android bytecode dalvik bytecode-manipulation smali

6
推荐指数
1
解决办法
1582
查看次数

是否可以在Android应用程序中注入代码?

我想在运行时在android应用程序中注入代码.我曾尝试使用dx工具在sdcard中生成dexfile,但是当我想要实例化时,它会失败.是否有任何工具可以注入生成新dalvik字节码的代码?我正在研究一些库,aspecjt或guice for android.使用脚本语言更好吗?

谢谢人们:)

android bytecode dalvik bytecode-manipulation

5
推荐指数
2
解决办法
6584
查看次数

字节代码检测 - 实现本机代理还是java代理?

如果我想使用字节码检测实现分析器,我应该使用JVMTI编写本机代理还是应该使用该包编写java代理java.lang.instrument

如果我想使用像ASM这样的库- 如果你想创建一个严肃的探查器似乎是强制性的 - 我必须使用java代理.这使我感到困惑,因为我认为本机代理可以完成Java代理可以做的所有事情.但对我来说,编写java代理似乎更容易.

还有替代品吗?是否应该使用java代理和本地代理组合?

bytecode-manipulation jvmti java-bytecode-asm

5
推荐指数
1
解决办法
1733
查看次数

使用ASM从方法体中删除异常

介绍:

我有一个(混淆)方法,我使用ASM打印,输出如下:

METHOD: m(ZB)Lcc;
--------------------------------------

L0:
{
    ALOAD_0
    GETFIELD   d/x I
    LDC  2036719157
    IMUL
    ISTORE
    GOTO  L1
}

L2:
{
    ALOAD_6
    ICONST_0
    LDC  -373364649
    ALOAD_0
    GETFIELD   d/at I
    IMUL
    ICONST_0
    INVOKEVIRTUAL   cc/y(III)V
    GOTO  L3
}

L4:
{
    ACONST_NULL
    ARETURN
}

L5:
{
    ILOAD_1
    IFEQ  L6
    LDC  -723220973
    ALOAD_0
    GETFIELD   d/an I
    IMUL
    ISTORE
    LDC  1671960653
    ALOAD_0
    GETFIELD   d/ad I
    IMUL
    ISTORE
    GOTO  L7
}

L8:
{
    LDC  1955946639
    ALOAD_0
    GETFIELD   d/au I
    IMUL
    IFEQ  L9
    ILOAD_2
    ICONST_1
    IF_ICMPEQ  L10
    NEW …
Run Code Online (Sandbox Code Playgroud)

java bytecode-manipulation java-bytecode-asm

5
推荐指数
1
解决办法
715
查看次数