Java 执行一段字节码
请考虑以下示例代码:Java 执行一段字节码,java,bytecode,bytecode-manipulation,Java,Bytecode,Bytecode Manipulation,请考虑以下示例代码: ... try { stm1 stm2 stm3 } catch(){ ... } ... 假设要运行代码,在try块中引发异常。执行流进入catch块 在这里,我想复制try块的字节码(可能使用ASM),对字节码应用一些修改(例如用stm4替换stm2),并在catch块中执行新的字节码 这是否可能不编译或加载新字节码,而只是像解释语言一样执行它 谢谢大家! 更新 我知道我可以事先编写正确的代码。问题不在于为什么,而在于如何做到这一点,以
...
try {
stm1
stm2
stm3
} catch(){
...
}
...
假设要运行代码,在try块中引发异常。执行流进入catch块
在这里,我想复制try块的字节码(可能使用ASM),对字节码应用一些修改(例如用stm4替换stm2),并在catch块中执行新的字节码
这是否可能不编译或加载新字节码,而只是像解释语言一样执行它
谢谢大家!
更新
我知道我可以事先编写正确的代码。问题不在于为什么,而在于如何做到这一点,以及如果可能的话
假设我必须动态计算新的try主体,并且必须在同一个对象中执行新代码(因为有局部变量和类变量)。以下是迄今为止最简单的
try {
stm1
stm2
stm3
} catch(){
stm1
stm4 // instead of stm2
stm3
}
你也可以用ASM做你建议的事情。然而,几乎所有您采取的替代方法都可能更简单。当您对正在运行的代码几乎没有控制权(或很少对性能有控制权)时,ASM通常是最好的选择。我假设您对代码有一定的控制权。不是字节码解决方案,而是Java:) 也许您可以通过在catch语句中键入逻辑来解决这个问题。一个缺点是try-catch块嵌套在每个块中,看起来很难看
但它认为字节码加载更易于维护。您最好设置一个状态机并动态确定下一个状态。比如:
int nextState = 0;
while(nextState != -1) {
try {
switch(nextState) {
case 0:
stm1;
++nextState;
break;
case 1:
stm2;
++nextState;
break;
case 2:
stm3;
nextState = -1;
break;
case 3:
stm4;
nextState = 2;
break;
}
} catch (Exception err) {
nextState = 3;
}
}
您可以将这些单独的语句分解为单独的方法或类,并使用Java反射调用单独的语句。然后取决于您通过这些反射调用迭代的顺序
另一种选择是动态生成代码,并使用JVM支持的脚本语言之一执行它,如BeanShell、Groovy、JavaScript/Rhino等。您希望实现什么?我们在一个确定性的世界里,为什么要执行一些已经再次失败的东西?为什么不编写要运行的不同代码?为什么特别关心字节码?您试图实现的更大目标是什么?您可以在catch块中执行
{stm1;stm4;stm3}
。这不需要ASM。如果你能用为什么需要使用ASM的信息更新你的问题,你的问题会更有意义。@Niko:如果你能提供一个有意义的例子,我打赌你会得到更好的答案。谢谢。但是让我们假设它必须动态地计算序列stm1,stm4,stm3,所以我不能在源代码中写它,它必须写在某个地方。根据您从何处获得它(以及以何种形式)确定哪种是最简单的解决方案。我可以在哪里编写它?我如何执行它。考虑一下代码应该很容易访问局部变量和类变量。当您编写字节码时,它是针对整个类的。(即使该类只有一个方法)如果您想轻松访问字段,它们必须是非私有的,或者您必须重写整个类。有关如何使用ASM编写字节码的示例,请参阅ASM文档。一旦你将字节码设置为byte[],你就可以使用defineClass加载它。所以,没有办法只执行从同一个类中提取的字节码,对吗?(就像在python中执行一系列代码)