10

コードから次のエラーが発生します。

スタックで 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);
}

このコードはデータに違いをもたらしますか?

4

5 に答える 5

4

Java 仮想マシンは、long および double データ型を含む操作に対して追加の検証を実行します。これは、次の非常に単純な理由からです。

long 型または double 型の値は、連続する 2 つのローカル変数を占有します。このような値は、より小さいインデックスを使用してのみアドレス指定できます。たとえば、ローカル変数配列のインデックス n に格納されている double 型の値は、実際にはインデックス n と n +1 のローカル変数を占有します。ただし、インデックス n +1 のローカル変数はロードできません。に収納できます。ただし、ローカル変数 n の内容は無効になります。

long または double 変数へのアクセスに不正な命令が使用されていると検証者が判断した場合 (たとえば、インデックス n のローカル変数を、double/long 変数を分割する整数または float として処理しようとする命令)、次に、前述のエラーにフラグが立てられます。

この場合、このバイトコードを生成したバイトコードジェネレーターを修正することを除いて、できることはあまりありません。これは、Java コンパイラ自体、または ASM、cglib、Javassist などのバイト コード操作フレームワークのいずれかです。

編集:

スタックトレースを確認すると、問題のクラスは (dashboard.jsp から) 生成されたサーブレットのようです。変換された JSP のコンパイルを含む JDK のアップグレードによって問題が解決するかどうかを確認する価値があります。

于 2011-05-23T14:34:18.383 に答える
4

これは、読み込まれているバイト コードが vm/compiler と完全に互換性がないことを示す検証エラーのようです。ほとんどの場合、使用している外部ライブラリからのものであるか、ビルドの過程で生成され、バグを示している可能性があります。

生成されたバイトコードを (直接的または間接的に) 使用していますか? AOP でよく使用されます。

また、Google はこのエラーに対して多くのヒットを出しています。それらを読んで、法案に合うものがあるかどうかを確認してください。

于 2011-05-23T14:13:38.057 に答える
1

これは のメッセージである可能性があります。このメッセージは、クラス ファイルが適切に形成されていても、何らかの内部矛盾またはセキュリティ上の問題が含まれていることを「ベリファイア」が検出した場合にjava.lang.VerifyErrorスローされます。

JVM 仕様のメモ (4.4.5):

すべての 8 バイト定数constant_poolは、クラス ファイルのテーブルで 2 つのエントリを占有します。CONSTANT_Long_infoまたはCONSTANT_Double_info構造体がconstant_poolインデックス n のテーブル内の項目である場合、プール内の次の使用可能な項目は index に配置されますn+2constant_poolインデックスn+1は有効である必要がありますが、使用できないと見なされます。

したがって、実際には、クラスファイルにはこの規則に違反する定数プールがあると思います。これは、通常の Java コンパイラでは発生しません (発生しないはずです) が、クラスファイル (AOP、BCEL、難読化、またはその他のプログラミング言語) を作成および変更する方法は他にもあります。スタックトレースを取得してみてください。問題のあるクラスファイルへのヒントが得られるはずです。

参考文献

于 2011-05-23T14:13:14.800 に答える
1

オートボクシングが関係するケースを考えることができます:フロートを格納するためにオートボクシングを使用しようとしていますか? これらが Double に自動ボックス化された場合、(おそらく JVM のバグが原因で) スタックから引き戻すときに、float が double よりも少ないバイト数を使用するため、バイト サイズ チェックが失敗し、このエラーがスローされます。これは、openjdk がソース コード (の一部) を見ている場合に当てはまるようです。Sun (申し訳ありませんが、Oracle!) JDK にも同じことが当てはまると思います。

于 2011-05-23T14:16:46.957 に答える