堆栈操作时出现奇怪的错误
作为我使用名为 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
方法中使用它。使用调试器,我可以看到 declaredMethods
为 null
,因此显然 getDeclaredMethods
调用正在死亡。 MyClient
类按以下方式定义为内部静态类:
public static class MyClient {
public static void main(String[] args[]) {
...
}
}
我不确定这是否与 declaredMethods
为 null
有关所以我尝试将课程提取到一个单独的课程中,但没有成功。
更新 3:
好的,缩小范围了。即使在主类中,以下内容也会引发异常:
System.out.println(MyClient.class.getDeclaredMethods());
As part of some simulations that I am running using a tool called JIST/SWANS I am getting some weird errors. This simulator has been written for Java 1.4 and I am attempting to port it to 1.5.
What I am trying to do is to compile the original code with the 1.5 SDK. The problem is that the simulator uses bcel to rewrite the bytecode so that JVM could be used for simulations. When I compile the code under the new SDK, I get the error given below. Can someone point me in the right direction to fix this? I know the byte code produced by 1.4 and 1.5 are somewhat different but I have no clue where to start looking from.
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)
UPDATE:
I narrowed down to this line from where the exception is being thrown:
private Method findMain(Class<?> c) throws NoSuchMethodException {
return c.getDeclaredMethod("main", new Class<?>[] { String[].class });
}
There is a main
method in the class which is being passed to this function so I have no clue why it is returning a null
.
UPDATE 2:
There is one function:
createNode(..., ..., ..., ..., MyClient.class, ..., ...)
which passes the MyClient.class
to a function that makes use of this in the findMain
method posted above. Using the debugger, I can see that declaredMethods
is null
so obviously the getDeclaredMethods
call is dying. The MyClient
class is defined as an inner static class in the following way:
public static class MyClient {
public static void main(String[] args[]) {
...
}
}
I am not sure if this has anything to do with declaredMethods
being null
so I tried extracting the class into a separate class but with no luck.
UPDATE 3:
Ok narrowed it down. The following throws an exception even in the main class:
System.out.println(MyClient.class.getDeclaredMethods());
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
也许下载 BCEL 的源代码并在该方法的第 135 行放置断点
会告诉您更多信息。显然,数组索引操作存在问题。
据我所知,BCEL 已经不再开发,所以如果存在 bug,如果你报告它,可能很难修复它。
ASM 是一个正在开发的更现代的字节码生成库。您可能已经知道这一点;但是如果您有该模拟器的源代码并且它没有过多使用 BCEL,那么您也许可以使用 ASM 重写它。当然,这样的事情通常是矫枉过正的。
Perhaps downloading BCEL's source code and putting a breakpoint at line 135 of this method
will tell you more. Obviously, there's a problem somewhere with array index manipulation.
From what I see, BCEL is no more in development, so if a bug exists, it might be difficult to have it fixed if you report it.
ASM is a more modern bytecode generation library that's under development. You probably already know this; but if you have that simulator's source code and it isn't using BCEL too much, you might be able to rewrite it using ASM. Of course, stuff like this is usually overkill.