【问题标题】:What does the error message "Attempt to split long or double on the stack" indicate?错误消息“尝试在堆栈上拆分长或双倍”表示什么?
【发布时间】:2011-08-31 04:37:07
【问题描述】:

我的代码出现以下错误:

尝试在堆栈上拆分 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中包含上述代码时。我确实得到了错误。否则,它可以工作。

进一步调查:

我已使用以下代码 sn-p 更新了dashboard.jsp 文件。我无法确定原因,但这段代码正在运行。

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

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

【问题讨论】:

  • 我以前从未见过。你用的是什么版本的JVM?
  • 我们使用 java 1.6 java 版本 "1.6.0_11" Java(TM) SE Runtime Environment (build 1.6.0_11-b03) Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode ,分享)
  • 是否可以发布导致此问题的代码的 sn-p?
  • 此错误是否以异常或错误类为前缀...如 java.lang.VerifyError ?
  • 您可以发布生成此代码的代码吗?看起来错误出在 JVM 本身。

标签: java verifyerror


【解决方案1】:

Java 虚拟机对涉及 long 和 double 数据类型的操作执行额外的验证,对于 very simple reason that

long 类型或 double 类型的值 占据两个连续的局部 变量。这样的值可能只 使用较小的索引解决。为了 例如,存储类型为 double 的值 在索引 n 处的局部变量数组中 实际上占据了局部变量 索引为 n 和 n +1;然而 索引 n +1 处的局部变量不能 从加载。可以存入。 但是,这样做会使 局部变量 n 的内容。

当验证器确定使用不正确的指令访问 long 或 double 变量时(例如,尝试将索引 n 处的局部变量视为整数或浮点数的指令,它会拆分 double/long变量),然后标记所述错误。

在这种情况下,除了修复生成此字节码的字节码生成器外,不能做很多事情。这可能是 Java 编译器本身,也可能是任何字节码操作框架,如 ASM、cglib 或 Javassist。

编辑:

查看堆栈跟踪后,似乎有问题的类恰好是生成的 servlet(来自dashboard.jsp)。有必要检查一下涉及编译已翻译 JSP 的 JDK 升级是否可以解决此问题。

【讨论】:

    【解决方案2】:

    这似乎是一个验证错误,表明正在加载的字节码不是 与您的 vm/编译器完全兼容。它很可能来自外部库 您使用的,或者它可能在您的构建过程中生成并指示错误。

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

    Google 也为这个错误提供了很多点击。阅读它们,看看是否符合要求。

    【讨论】:

      【解决方案3】:

      我可以想到一个涉及自动装箱的案例:您是否尝试使用自动装箱来存储浮点数?如果这些最终自动装箱到 Double 中,那么当您将它们从堆栈中拉回时(可能是由于 JVM 错误),因为 float 占用的字节数少于 double 字节大小检查失败并抛出此错误。这似乎是 openjdk 查看(部分)他们的源代码的情况——我猜这同样适用于 Sun(对不起,Oracle!)JDK。

      【讨论】:

        【解决方案4】:

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

        JVM 规范说明(4.4.5):

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

        所以实际上猜想,在类文件中有一个违反此规则的常量池。这不会(不应该)在普通的 java 编译器中发生,但是有更多的方法可以创建和更改类文件(AOP、BCEL、混淆或其他编程语言)。尝试获取堆栈跟踪,它应该会提示有问题的类文件。

        进一步阅读

        【讨论】:

          【解决方案5】:

          能否通过更改代码来解决问题:

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

          进入:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-08-06
            • 1970-01-01
            • 1970-01-01
            • 2015-08-04
            • 1970-01-01
            • 2021-10-04
            • 2016-09-23
            • 1970-01-01
            相关资源
            最近更新 更多