我正在尝试bcel通过在特定指令之前插入invoke来修改方法。看来我的工具会产生一个不同的堆栈表,bcel包本身不能自动生成它。因此,我的工具化类文件包含旧的stackmap表,这将导致jvm出错。我尝试过使用removeCodeAttributes ( MethodGen的方法)来删除所有的代码属性。它可以在简单的情况下工作,例如包装函数。在我的情况下已经行不通了。
public class Insert{
public static void main(String[] args) throws ClassFormatException, IOException{
Insert isrt = new Insert();
String className = "StringBuilder.class";
JavaClass jclzz = new ClassParser(className).parse();
ClassGen cgen = new ClassGen(jclzz);
ConstantPoolGen cpgen = cgen.getConstantPool();
MethodGen mgen = new MethodGen(jclzz.getMethods()[1], className, cpgen);
InstructionFactory ifac = new InstructionFactory(cgen);
InstructionList ilist = mgen.getInstructionList();
for (InstructionHandle ihandle : ilist.getInstructionHandles()){
System.out.println(ihandle.toString());
}
InstructionFinder f = new InstructionFinder(ilist);
InstructionHandle[] insert_pos = (InstructionHandle[])(f.search("invokevirtual").next());
Instruction inserted_inst = ifac.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC);
System.out.println(inserted_inst.toString());
ilist.insert(insert_pos[0], inserted_inst);
mgen.setMaxStack();
mgen.setMaxLocals();
mgen.removeCodeAttributes();
cgen.replaceMethod(jclzz.getMethods()[1], mgen.getMethod());
ilist.dispose();
//output the file
FileOutputStream fos = new FileOutputStream(className);
cgen.getJavaClass().dump(fos);
fos.close();
}
}发布于 2014-10-20 11:13:22
删除StackMapTable并不是修复错误StackMapTable的适当解决方案。重要的例子是:
4.7.4.StackMapTable属性 在版本号为50.0或以上的
class文件中,如果方法的Code属性没有StackMapTable属性,则它具有隐式堆栈映射属性(第4.10.1节)。此隐式堆栈映射属性等效于StackMapTable属性,number_of_entries等于零。
因为StackMapTable必须对每个分支目标都有显式的条目,所以这样的隐式StackMapTable只适用于不带分支的方法。但是在这些情况下,该方法通常没有显式的StackMapTable,因此您就不会遇到这个问题(除非该方法有您的工具删除的分支)。
另一个结论是,如果将类文件版本号修补为低于StackMapTable的值,则可以删除50。当然,只有当您不需要在版本50或更新的…中引入任何类文件功能时,这才是解决方案。
有一个宽限期,JVM支持类文件的回退模式,只有在像您这样的场景中,工具支持并不是最新的。(请参阅-XX:+FailoverToOldVerifier或-XX:-UseSplitVerifier)但是宽限期现在已经结束了,这种支持已经被拒绝了,也就是说Java8JVM不再支持回落模式了。
如果您想跟上Java开发和使用这些新版本特性的更新类文件,那么您只有两个选择:
StackMapTableStackMapTable属性的工具,例如ASM,(参见java-字节码-asm)支持它https://stackoverflow.com/questions/26072210
复制相似问题