procyon
procyon copied to clipboard
IndexOutOfBoundsExceptions
When decompiling particular classes, I sometimes encounter IndexOutOfBoundsExceptions, which manifest in the decompiled code as shown below:
//
// This method could not be decompiled.
//
// Original Bytecode:
//
// [...]
//
// The error that occurred was:
//
// java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0
// at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
// at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
// at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
// [...]
I tried to look into this myself, but I had to realize, that I just understand too little of the decompilation process to find the root cause. This problem is present since I started using your marvelous decompiler back in 2018 and also applies to the most recent v0.6.0 release. Due to the fact, that I used the decompiler primarily on licensed legacy code, I never found a way to provide some reproduction steps here.
Well, up to now. By accident I found another class, that shows the same problem, but is freely available - compiled and in source. (BTW: There is surely no need to decompile kotlin-stdlib, but as it shows the exact same exception as on the legacy java code, I use it for reproduction here.)
So, please consider the following reproduction steps:
- Download Kotlin-Stdlib (https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.7.20/kotlin-stdlib-1.7.20.jar)
- Perform decompile on this JAR (my command was
java -jar procyon-decompiler-0.6.0.jar -ln -sl -o /tmp/out kotlin-stdlib-1.7.20.jar
- Open
/tmp/out/kotlin/SynchronizedLazyImpl.java
and find the inline comments of the decompiler logging the java.lang.IndexOutOfBoundsException.
Some observations:
- There seem to be several inline exceptions in other classes, too, but with other causes. I don't want to overcomplicate things in this issue, so I'm fine with sticking to the
IndexOutOfBoundsException
for now. - While most of the exceptions happen silently (only within the inline-comments of decompiled classes), one
IndexOutOfBoundsException
is actually thrown in the console (afterDecompiling kotlin/text/StringsKt__StringsKt...
). But this one seems unrelated to the one inSynchronizedLazyImpl.java
.
If you require more details (like the full inline comment), let me know. I didn't want to blow up the description here.
Inline comment found in SynchronizedLazyImpl.java
:
//
// This method could not be decompiled.
//
// Original Bytecode:
//
// 1: getfield kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;
// 4: astore_1 /* _v1 */
// 5: aload_1 /* _v1 */
// 6: getstatic kotlin/UNINITIALIZED_VALUE.INSTANCE:Lkotlin/UNINITIALIZED_VALUE;
// 9: if_acmpeq 14
// 12: aload_1 /* _v1 */
// 13: areturn
// 14: aload_0 /* this */
// 15: getfield kotlin/SynchronizedLazyImpl.lock:Ljava/lang/Object;
// 18: astore_2
// 19: aload_2
// 20: astore_3
// 21: aload_3
// 22: monitorenter
// 23: nop
// 24: iconst_0
// 25: istore $i$a$-synchronized-SynchronizedLazyImpl$value$1
// 27: aload_0 /* this */
// 28: getfield kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;
// 31: astore _v2
// 33: aload _v2
// 35: getstatic kotlin/UNINITIALIZED_VALUE.INSTANCE:Lkotlin/UNINITIALIZED_VALUE;
// 38: if_acmpeq 46
// 41: aload _v2
// 43: goto 74
// 46: aload_0 /* this */
// 47: getfield kotlin/SynchronizedLazyImpl.initializer:Lkotlin/jvm/functions/Function0;
// 50: dup
// 51: invokestatic kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
// 54: invokeinterface kotlin/jvm/functions/Function0.invoke:()Ljava/lang/Object;
// 59: astore typedValue
// 61: aload_0 /* this */
// 62: aload typedValue
// 64: putfield kotlin/SynchronizedLazyImpl._value:Ljava/lang/Object;
// 67: aload_0 /* this */
// 68: aconst_null
// 69: putfield kotlin/SynchronizedLazyImpl.initializer:Lkotlin/jvm/functions/Function0;
// 72: aload typedValue
// 74: nop
// 75: astore null
// 77: aload_3
// 78: monitorexit
// 79: aload 4
// 81: goto 91
// 84: astore 4
// 86: aload_3
// 87: monitorexit
// 88: aload 4
// 90: athrow
// 91: areturn
// Signature:
// ()TT;
// StackMapTable: 00 05 FC 00 0E 07 00 05 FF 00 1F 00 06 07 00 02 07 00 05 07 00 05 07 00 05 01 07 00 05 00 00 5B 07 00 05 FF 00 09 00 04 07 00 02 07 00 05 07 00 05 07 00 05 00 01 07 00 41 FF 00 06 00 06 07 00 02 07 00 05 07 00 05 07 00 05 07 00 05 07 00 05 00 01 07 00 05
// Exceptions:
// Try Handler
// Start End Start End Type
// ----- ----- ----- ----- ----
// 23 77 84 91 Any
// 84 86 84 91 Any
//
// The error that occurred was:
//
// java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0
// at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
// at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
// at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
// at java.base/java.util.Objects.checkIndex(Objects.java:372)
// at java.base/java.util.ArrayList.remove(ArrayList.java:536)
// at com.strobel.assembler.ir.StackMappingVisitor.pop(StackMappingVisitor.java:267)
// at com.strobel.assembler.ir.StackMappingVisitor$InstructionAnalyzer.execute(StackMappingVisitor.java:599)
// at com.strobel.assembler.ir.StackMappingVisitor$InstructionAnalyzer.visit(StackMappingVisitor.java:398)
// at com.strobel.decompiler.ast.AstBuilder.performStackAnalysis(AstBuilder.java:2086)
// at com.strobel.decompiler.ast.AstBuilder.build(AstBuilder.java:108)
// at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:203)
// at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
// at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
// at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
// at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
// at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
// at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
// at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:144)
//