字节码操作的合法用途是什么以及人们如何在实践中实现基于字节码操作的解决方案?
更新:我应该更清楚地说明这个问题实际上是关于人们使用什么模式和技术来使代码在字节码操作的帮助下飞行.
像已经提到的面向方面编程或动态构建代理对象和类似技术的东西.
用法示例:
我想在类字段上添加一个自定义注释@MyContainer,然后在所有这些字段上自动添加相关的Hibernate注释(取决于字段类型和属性).
另外,我需要将JAXB XmlType注释添加到类中,并将类型名称基于类名.
我还希望基于其类型等向字段添加注释.所有添加的注释应该在运行时可用(因此hibernate/JAXB可以找到它们).
我知道以下选项:
我的主要目标是:
如果已经完成此类工作的人能够为这样的任务推荐最佳方法(也许还有潜在的陷阱),我将不胜感激.
java compiler-construction annotations bytecode-manipulation
为了能够在运行时检测何时进行比较(或任何其他操作,如*, - ,/,>,<,......
应该使用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
我的计划是编写一个基于注释的缓存框架,用于缓存方法的返回值.当第一次使用特定参数调用方法时,缓存应该存储方法返回值.当使用相同的参数第二次调用相同的方法时,该方法应该从缓存返回先前计算的结果,而不是再次执行其代码.我的注释看起来像这样:
@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) 使用像javaassist这样的API执行字节码操作,在编译后修改类文件.但是,如果优化了java代码,那么修改是否可以在错误的地方执行?有办法避免这个问题吗?常规Java和Android之间的故事有何不同?
java android bytecode-manipulation javassist java-bytecode-asm
当访问方法指令a.doAnother(account.getId);使用visitMethodInsn()时ASM.我需要从方法参数获取帐户account.getId()类型,帐户类型是Account.但是我得到的返回类型account.getId()是long.如何获得Account此处的帐户类型?
我正在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应用程序中注入代码.我曾尝试使用dx工具在sdcard中生成dexfile,但是当我想要实例化时,它会失败.是否有任何工具可以注入生成新dalvik字节码的代码?我正在研究一些库,aspecjt或guice for android.使用脚本语言更好吗?
谢谢人们:)
如果我想使用字节码检测实现分析器,我应该使用JVMTI编写本机代理还是应该使用该包编写java代理?java.lang.instrument
如果我想使用像ASM这样的库- 如果你想创建一个严肃的探查器似乎是强制性的 - 我必须使用java代理.这使我感到困惑,因为我认为本机代理可以完成Java代理可以做的所有事情.但对我来说,编写java代理似乎更容易.
还有替代品吗?是否应该使用java代理和本地代理组合?
我有一个(混淆)方法,我使用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)