我的代码中出现以下错误:

尝试在堆栈上拆分 long 或 double

我对这个错误的根源一无所知,也不知道如何调试它。这说明了一个什么样的问题呢?我该如何修复它?

[ERROR]  [Mon May 23 14:29:46 IST 2011]   [(class: org/apache/jsp/dashboard_jsp, method: _jspService signature:     (Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V) Attempt to split long or double on the stack]  [10.97.34.222] hddlntdsz2350  [ session not set ] 
java.lang.VerifyError: (class: org/apache/jsp/dashboard_jsp, method: _jspService signature: (Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V) Attempt to split long or double on the stack
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
at java.lang.Class.getConstructor0(Class.java:2699)
at java.lang.Class.newInstance0(Class.java:326)
at java.lang.Class.newInstance(Class.java:308)
at org.jboss.web.tomcat.service.TomcatInjectionContainer.newInstance(TomcatInjectionContainer.java:273)

问题代码:我创建了一个模型,如下所示

public class DashboardViewModel implements Serializable {

/** defalut serialization id */
private static final long serialVersionUID = 1L;

/**
 * Collection representing all the services
 */
private Map<Long, ServiceCustomerModel> serviceDataMap;

}

在特定的 JSP 页面上,我正在执行以下操作。

for (Long serviceId : dashboardViewModel.getServices()) {
           Service service = dashboardViewModel.getService(serviceId);
}

getServices 上述目标类中的方法如下。

public Set<Long> getServices() {
    return this.serviceDataMap.keySet();
}

当在jsp中包含上述代码时。我确实得到了错误。否则,它会起作用。

进一步调查:

我已使用以下代码片段更新了dashboard.jsp 文件。我无法确定为什么,但这段代码正在运行。

ArrayList<Long> test = new ArrayList<Long>();
test.addAll(dashboardViewModel.getServices());
for (long serviceId : test) {
    Service service = dashboardViewModel.getService(serviceId);
}

这段代码对数据有什么影响吗?

有帮助吗?

解决方案

Java虚拟机对非常简单的原因

类型长或型双 占用两个连续的地方 变量。这样的价值只能是 使用较小的索引解决。为了 示例,类型双存储的值 在索引n的局部变量阵列中 实际上占据局部变量 使用索引n和n +1;然而 index n +1处的局部变量不能是 加载。它可以存储到。 但是,这样做是无效的 局部变量的内容n。

当验证程序确定用于访问长期或双变量的不正确指令时(例如,尝试将index n处理局部变量的指令,作为整数或浮点,它们拆分双/长变量),然后标记上述错误。

在这种情况下,不可能完成,除了修复生成此字节代码的字节码生成器之外。这可以是Java编译器本身,或者或任何字节代码操作框架,如ASM,CGLIB或Javassist。

编辑:

查看堆栈特许道后,似乎有问题的类恰好是生成的servlet(从仪表板.jsp)。值得检查涉及翻译的JSP汇编的JDK升级是否会解决问题。

其他提示

这似乎是一个验证错误,指示正在加载的字节代码不是 与VM / Compiler完全兼容。它最有可能来自外部图书馆 您使用或它可能在构建过程中生成并指示错误。

您是否使用(直接或间接地)任何生成的字节码?它经常与AOP一起使用。

还谷歌为此错误提供了很多命中。阅读它们,看看是否有任何适合账单。

我可以想到一个涉及autoboxing的案例:您是否尝试使用AutoBoxing来存储Float的?如果这些最终将自动扩展到Double,那么当您从堆栈中拉回它们时(可能是由于JVM错误),因为Float取低于双倍的字节大小检查失败并且抛出此错误。这似乎是openjdk看(一些)他们的源代码 - 我猜想同样适用于太阳(对不起,oracle!)jdk。

这是一条可能的消息 java.lang.VerifyError, ,被抛出 当“验证程序”检测到类文件虽然格式良好,但包含某种内部不一致或安全问题时。

JVM 规范注释 (4.4.5):

所有 8 字节常量占用两个条目 constant_pool 类文件的表。如果一个 CONSTANT_Long_info 或者 CONSTANT_Double_info 结构是 中的项目 constant_pool 表位于索引 n 处,则池中的下一个可用项目位于索引处 n+2. 。这 constant_pool 指数 n+1 必须有效但被视为不可用。

所以实际上猜测,类文件中有一个常量池打破了这个规则。使用普通的 java 编译器不会(不应该)发生这种情况,但有更多方法来创建和更改类文件(AOP、BCEL、混淆或其他编程语言)。尝试获取堆栈跟踪,它应该为有问题的类文件提供提示。

进一步阅读

可以通过更改代码来修复问题:

for (long serviceId : test) {
    Service service = dashboardViewModel.getService(serviceId);
}
.

进入:

for (Long serviceId : test) {
    Service service = dashboardViewModel.getService(serviceId);
}
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top