Question

Using ASM 4. I'm generating bytecode on the fly from another language. It's generating the following, but I'm not clear on what's going on. My guess is that the try/catch block is interfering with the stack. The first two lines are loading a Lambda2 which is then needed to be the deepest item on the stack at the very end, but I don't understand what is making it disappear along the way.

It appears that at instruction 13 the stack disappears. That's where it enters a try/catch block. Does the stack get tossed out when it enters a try/catch block? If so, that would explain the problem.

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
Was it helpful?

Solution

Yes the stack is empty when entering a catch() block. Since the catch handler cannot know from which instruction the exception occured inside the try{} block, the stack could be in any of the possible states of the try{} block.

Also, any local variables modified within the try{} block can not be assumed to be in any specific state when entering the catch() block, but this is not a problem in your case.

So, when exiting the catch block you need to make sure the stack is in the same state as if no exception was thrown. In this case, you need to populate the stack with a Lambda2 object and a Long object by the time the code reaches L6.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top