0

ASM 4 を使用しています。別の言語からオンザフライでバイトコードを生成しています。以下を生成していますが、何が起こっているのかわかりません。私の推測では、try/catch ブロックがスタックに干渉していると思われます。最初の 2 行は Lambda2 をロードしています。これは最後にスタックの最も深い項目である必要がありますが、途中でそれが消えている理由がわかりません。

命令 13 でスタックが消えるようです。ここで、try/catch ブロックに入ります。スタックは、try/catch ブロックに入ると捨てられますか? もしそうなら、それは問題を説明するでしょう。

java.lang.RuntimeException: Error at instruction 43: Cannot pop operand off an empty stack. apply()Ljava/lang/Object;
00000 R . .  :  :    L0
00001 R . .  :  :     LINENUMBER 1 L0
00002 R . .  :  :     LDC "foo"
00003 R . .  : R  :     INVOKESTATIC com/stralos/asm/ASMUtil.getUserFunc (Ljava/lang/Object;)Ljava/lang/Object;
00004 R . .  : R  :    L1
00005 R . .  : R  :     LINENUMBER 1 L1
00006 R . .  : R  :     CHECKCAST com/stralos/lang/Lambda2
00007 R . .  : R  :    L2
00008 R . .  : R  :     LINENUMBER 1 L2
00009 R . .  : R  :     LDC 1
00010 R . .  : R J  :     INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
00011 R . .  : R R  :    L3
00012 R . .  : R R  :     LINENUMBER 1 L3
00013 ?        :     LDC 1
00014 ?        :     INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
00015 ?        :    L4
00016 ?        :     LINENUMBER 1 L4
00017 ?        :     ASTORE 1
00018 ?        :    L5
00019 ?        :     GOTO L6
00020 R . .  : R  :    L7
00021 R . .  : R  :     LINENUMBER 1 L7
00022 R . .  : R  :    FRAME SAME1 java/lang/Throwable
00023 R . .  : R  :     ASTORE 2
00024 R . R  :  :    L8
00025 R . R  :  :     LINENUMBER 1 L8
00026 R . R  :  :     NEW shen/lambda/ToRun$1
00027 R . R  : R  :     DUP
00028 R . R  : R R  :    L9
00029 R . R  : R R  :     LINENUMBER 1 L9
00030 R . R  : R R  :     INVOKESPECIAL shen/lambda/ToRun$1.<init> ()V
00031 R . R  : R  :    L10
00032 R . R  : R  :     LINENUMBER 1 L10
00033 R . R  : R  :     CHECKCAST com/stralos/lang/Lambda1
00034 R . R  : R  :     ALOAD 2
00035 R . R  : R R  :     INVOKEVIRTUAL com/stralos/lang/Lambda1.apply (Ljava/lang/Object;)Ljava/lang/Object;
00036 R . R  : R  :     ASTORE 1
00037 R R R  :  :    L6
00038 R R R  :  :     LINENUMBER 1 L6
00039 R R R  :  :    FRAME FULL [shen/eval/ToEvaluate$0 java/lang/Object] [com/stralos/lang/Lambda2 java/lang/Long]
00040 R R R  :  :     ALOAD 1
00041 R R R  : R  :    L11
00042 R R R  : R  :     LINENUMBER 1 L11
00043 R R R  : R  :     INVOKEVIRTUAL com/stralos/lang/Lambda2.apply (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
00044 ?        :     ARETURN
00045 ?        :    L12
     TRYCATCHBLOCK L3 L5 L7 java/lang/Throwable
4

1 に答える 1

1

はい、catch() ブロックに入るとき、スタックは空です。catch ハンドラーは try{} ブロック内で例外が発生した命令を認識できないため、スタックは try{} ブロックの可能な状態のいずれかにある可能性があります。

また、try{} ブロック内で変更されたローカル変数は、catch() ブロックに入るときに特定の状態にあると想定することはできませんが、これは問題ではありません。

そのため、catch ブロックを終了するときは、スタックが例外がスローされなかった場合と同じ状態であることを確認する必要があります。この場合、コードが L6 に到達するまでに、スタックに Lambda2 オブジェクトと Long オブジェクトを設定する必要があります。

于 2013-02-08T06:21:20.760 に答える