向Java字节码中的函数添加参数

向Java字节码中的函数添加参数,java,bytecode,java-bytecode-asm,bytecode-manipulation,Java,Bytecode,Java Bytecode Asm,Bytecode Manipulation,我已经编译了带有X.class文件的.jar插件X.class文件包含一个带有参数Y的方法Y(字符串s1、字符串s2…)。我需要传递到另一个字符串-因此我启动了reJ和dirtyJoe,编辑了Y方法的描述符,将最大局部变量计数从8更改为9,添加了新的局部变量,将其设置为与以前的变量相同,只是给了它另一个索引,编辑了代码并保存了该方法。我将其打包回.jar文件,并尝试使用新版本的插件进行统一编译。不幸的是,它给了我一个错误,说我的新变量无效- EXCEPTION FROM SIMULATION:

我已经编译了带有
X.class
文件的.jar插件
X.class
文件包含一个带有参数Y的方法Y(字符串s1、字符串s2…)。我需要传递到另一个字符串-因此我启动了reJ和dirtyJoe,编辑了Y方法的描述符,将最大局部变量计数从8更改为9,添加了新的局部变量,将其设置为与以前的变量相同,只是给了它另一个索引,编辑了代码并保存了该方法。我将其打包回.jar文件,并尝试使用新版本的插件进行统一编译。不幸的是,它给了我一个错误,说我的新变量无效-

EXCEPTION FROM SIMULATION:
local 0008: invalid

...at bytecode offset 00000036
locals[0000]: Ljava/lang/String;
locals[0001]: Ljava/lang/String;
locals[0002]: Ljava/lang/String;
locals[0003]: Ljava/lang/String;
locals[0004]: Ljava/lang/String;
locals[0005]: [B
locals[0006]: Landroid/net/Uri;
locals[0007]: Landroid/content/Intent;
locals[0008]: <invalid>
stack[0001]: Landroid/content/Intent;
stack[top0]: string{"android.intent.extra.TEXT"}
...while working on block 0036
...while working on method StartShareIntentMedia:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
...while processing StartShareIntentMedia (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
...while processing com/androidnative/features/social/common/SocialGate.class
模拟异常: 本地0008:无效 …字节码偏移量为000000 36 locals[0000]:Ljava/lang/String; 局部变量[0001]:Ljava/lang/String; locals[0002]:Ljava/lang/String; locals[0003]:Ljava/lang/String; locals[0004]:Ljava/lang/String; 本地人[0005]:[B] locals[0006]:Landroid/net/Uri; 本地人[0007]:Landroid/内容/意图; 本地人[0008]: 堆栈[0001]:Landroid/content/Intent; 堆栈[top0]:字符串{“android.intent.extra.TEXT”} …在处理0036块时 …在使用方法StartShareIntentMedia时:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V …在处理StartShareIntentMedia时(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V …在处理com/androidnative/features/social/common/SocialGate.class时
这是我第一次使用Java字节码,希望能得到一些帮助。谢谢!

编辑字节码不适合胆小的人。我建议在开始之前阅读JVM规范

也就是说,根据你的描述,有几件事你可能做错了

在方法开始时,方法参数在局部变量插槽
0
n-1
中传递。您不能只为新的局部变量选择任何索引,必须在最后一个当前参数之后使用索引。如果字节码已经将该插槽用于其他内容,则必须调整或者,您可以在方法的开头添加移动序列(即,
aload n
astore y
),这不会影响该插槽在方法后面作为局部变量的使用

如果您有调试信息,如
LocalVariableTable
,则必须调整其中的所有引用。如果字节码有
StackMapTable
,则必须调整该值。假设代码未使用
invokedynamic
,则可能更容易将字节码版本更改回
50.0
,并且完全删除堆栈映射表

接下来,您必须更改方法描述符。描述符本质上给出了方法的签名,在字节码中,方法总是由(类、名称、描述符)标识三元组。您需要在描述符末尾的最后一个右括号和返回类型之前添加一个字符串作为参数。如果常量池中还没有新描述符,则必须将其添加到常量池中

然后,您必须调整方法的定义以引用新的描述符,并调整调用该方法的每个位置(最好不要涉及继承和反射!)


当然,您还必须调整每个callsite以实际传入新参数。

我有点困惑,为什么您要尝试在字节码级别调用参数-您能解释一下为什么使用提供的函数不能满足您的需要吗?因为我需要在这个函数中调用的android Intent中添加一个字符串Ion非常感谢您的回答!我不再需要我正在开发的功能,但我仍将在空闲时间尝试实现这一点;)v50中添加了
StackMapTable
,因此在删除
StackMapTable
s时,您必须使用50之前的版本。除了
invokedynamic
,您还将失去所有J8功能,
static
接口
s中的默认方法,以及类型注释和反射方法参数…@Holger Legacy verification fallback在版本50中是可选的。因此,如果您想学究并保证支持,您需要返回到49,但您关心的任何JVM都将返回到版本50中的Legacy verification当stackmap不存在时,使用v50。但是,当v49和v50之间的唯一区别是引入stackmaps时,为什么删除stackmaps的人要转到v50?