在堆栈操作上获得奇怪的错误

时间:2010-11-30 05:31:41

标签: java debugging bytecode bcel

作为我使用名为JIST / SWANS的工具运行的一些模拟的一部分,我得到了一些奇怪的错误。这个模拟器是为Java 1.4编写的,我试图将它移植到1.5。

我要做的是使用1.5 SDK编译原始代码。问题是模拟器使用bcel重写字节码,以便JVM可用于模拟。当我在新SDK下编译代码时,我得到下面给出的错误。有人能指出我正确的方向来解决这个问题吗?我知道1.4和1.5产生的字节代码有些不同,但我不知道从哪里开始查找。

java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.remove(ArrayList.java:390)
    at org.apache.bcel.verifier.structurals.OperandStack.pop(OperandStack.java:135)
    at org.apache.bcel.verifier.structurals.ExecutionVisitor.visitPUTFIELD(ExecutionVisitor.java:1048)
    at org.apache.bcel.generic.PUTFIELD.accept(PUTFIELD.java:78)
    at jist.runtime.RewriterFlow.execute(RewriterFlow.java:235)
    at jist.runtime.RewriterFlow.doFlow(RewriterFlow.java:187)
    at jist.runtime.RewriterTraversalContinuableMethods.doMethod(Rewriter.java:3059)
    at jist.runtime.ClassTraversal.processMethodGen(ClassTraversal.java:136)
    at jist.runtime.ClassTraversal.processClassGen(ClassTraversal.java:96)
    at jist.runtime.ClassTraversal.processClass(ClassTraversal.java:63)
    at jist.runtime.Rewriter.rewriteClass(Rewriter.java:621)
    at jist.runtime.Rewriter.findClass(Rewriter.java:410)
    at jist.runtime.Rewriter.loadClass(Rewriter.java:367)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
    at java.lang.Class.getDeclaredMethod(Class.java:1935)
    at jist.swans.app.AppJava.findMain(AppJava.java:86)
    at jist.swans.app.AppJava.<init>(AppJava.java:61)
    at driver.aodvtest.createNode(aodvtest.java:192)
    at driver.aodvtest.createSim(aodvtest.java:235)
    at driver.aodvtest.main(aodvtest.java:277)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at jist.runtime.Bootstrap$JavaMain.startSimulation(Bootstrap.java:163)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at jist.runtime.Controller.processEvent(Controller.java:650)
    at jist.runtime.Controller.eventLoop(Controller.java:428)
    at jist.runtime.Controller.run(Controller.java:457)
    at java.lang.Thread.run(Thread.java:619)

java.lang.NullPointerException
    at driver.aodvtest.createNode(aodvtest.java:198)
    at driver.aodvtest.createSim(aodvtest.java:235)
    at driver.aodvtest.main(aodvtest.java:277)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at jist.runtime.Bootstrap$JavaMain.startSimulation(Bootstrap.java:163)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at jist.runtime.Controller.processEvent(Controller.java:650)
    at jist.runtime.Controller.eventLoop(Controller.java:428)
    at jist.runtime.Controller.run(Controller.java:457)
    at java.lang.Thread.run(Thread.java:619)

更新 我缩小到抛出异常的那一行:

private Method findMain(Class<?> c) throws NoSuchMethodException {
  return c.getDeclaredMethod("main", new Class<?>[] { String[].class });
}

类中有一个main方法正在传递给这个函数,所以我不知道它为什么返回null

更新2:

有一个功能:

createNode(..., ..., ..., ..., MyClient.class, ..., ...)

MyClient.class传递给在上面发布的findMain方法中使用此功能的函数。使用调试器,我可以看到declaredMethodsnull,所以很明显getDeclaredMethods来电正在死亡。 MyClient类以下列方式定义为内部静态类:

public static class MyClient {
   public static void main(String[] args[]) {

      ...

   }
}

我不确定这是否与declaredMethods null有关,所以我尝试将该类提取到一个单独的类中,但没有运气。

更新3:

好吧缩小范围。以下内容甚至在主类中引发异常:

System.out.println(MyClient.class.getDeclaredMethods());

1 个答案:

答案 0 :(得分:1)

也许下载BCEL的源代码并在此方法的第135行设置断点

org.apache.bcel.verifier.structurals.OperandStack.pop(OperandStack.java:135)

会告诉你更多。显然,在某些地方使用数组索引操作存在问题。

从我看到的情况来看,BCEL不再处于开发阶段,因此如果存在错误,如果报告它可能很难修复它。

ASM是一个更现代的字节码生成库,正在开发中。你可能已经知道了;但是如果你有那个模拟器的源代码并且它没有过多地使用BCEL,你可能可以使用ASM重写它。当然,像这样的东西通常是矫枉过正的。