After proguarding next code java fails with VerificationError
package test
import java.io.File
fun File.descendantRelativeTo(base: File): File {
val prefix = base.canonicalPath
val answer = this.canonicalPath
return if (answer.startsWith(prefix)) {
val prefixSize = prefix.length
if (answer.length > prefixSize) {
File(answer.substring(prefixSize + 1))
} else File("")
} else {
this
}
}
fun main(args: Array<String>) {
File("/test").descendantRelativeTo(File("/test"))
}
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 105
Exception Details:
Location:
test/FileUtilsKt.main([Ljava/lang/String;)V @105: iload_0
Reason:
Type uninitialized 78 (current frame, locals[2]) is not assignable to 'java/io/File' (stack map, locals[2])
Current Frame:
bci: @92
flags: { }
locals: { integer, 'java/lang/String', uninitialized 78, uninitialized 78 }
stack: { 'java/lang/String', 'java/lang/String' }
Stackmap Frame:
bci: @105
flags: { }
locals: { integer, top, 'java/io/File', 'java/io/File' }
stack: { 'java/lang/String' }
Bytecode:
0x0000000: 2a12 05b8 0017 bb00 0a59 1204 b700 11bb
0x0000010: 000a 5912 04b7 0011 4c59 4b12 02b8 0017
0x0000020: 2b12 06b8 0017 2bb6 0012 4c2a b600 1259
0x0000030: 4d2b 5912 08b8 0016 0305 01b8 0018 9900
0x0000040: 4b2b b600 133b 2cb6 0013 1aa4 0032 bb00
0x0000050: 0a59 2c4c 1a04 603b 4e4d 2b59 c700 0dbb
0x0000060: 000d 5912 07b7 0015 bf1a b600 1459 1203
0x0000070: b800 164b 2c2d 2ab7 0011 a700 10bb 000a
0x0000080: 5912 01b7 0011 a700 042a 57b1
Stackmap Table:
full_frame(@105,{Integer,Top,Object[#10],Object[#10]},{Object[#12]})
full_frame(@125,{},{})
append_frame(@137,Object[#10])
full_frame(@138,{},{Object[#10]})
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Simplified case :
Bytecode before transfromation
public static final void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=4, locals=16, args_size=1
0: aload_0
1: ldc #9 // String args
3: invokestatic #15 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: new #17 // class test/C
9: dup
10: bipush 42
12: ldc #19 // String 1
14: invokestatic #25 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
17: checkcast #27 // class java/lang/Iterable
20: astore_1
21: istore 13
23: astore 12
25: astore 11
27: aload_1
28: astore_2
29: new #29 // class java/util/ArrayList
32: dup
33: aload_1
34: bipush 10
36: invokestatic #33 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
39: invokespecial #37 // Method java/util/ArrayList."<init>":(I)V
42: checkcast #39 // class java/util/Collection
45: astore_3
46: aload_2
47: invokeinterface #43, 1 // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
52: astore 4
54: aload 4
56: invokeinterface #49, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
61: ifeq 110
64: aload 4
66: invokeinterface #53, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
71: astore 5
73: aload_3
74: aload 5
76: checkcast #55 // class java/lang/String
79: astore 6
81: astore 14
83: aload 6
85: astore 7
87: aload 7
89: invokestatic #61 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
92: invokestatic #65 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
95: astore 15
97: aload 14
99: aload 15
101: invokeinterface #69, 2 // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
106: pop
107: goto 54
110: aload_3
111: checkcast #71 // class java/util/List
114: astore 14
116: aload 11
118: aload 12
120: iload 13
122: aload 14
124: invokespecial #74 // Method test/C."<init>":(ILjava/util/List;)V
127: astore_1
128: getstatic #80 // Field java/lang/System.out:Ljava/io/PrintStream;
131: aload_1
132: invokevirtual #86 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
135: return
LocalVariableTable:
Start Length Slot Name Signature
83 9 6 it Ljava/lang/String;
83 9 8 $i$a$1$map I
73 34 5 item$iv$iv Ljava/lang/Object;
46 65 2 $receiver$iv$iv Ljava/lang/Iterable;
46 65 3 destination$iv$iv Ljava/util/Collection;
46 65 9 $i$f$mapTo I
27 87 1 $receiver$iv Ljava/lang/Iterable;
27 87 10 $i$f$map I
0 136 0 args [Ljava/lang/String;
LineNumberTable:
line 6: 6
line 8: 27
line 9: 46
line 10: 73
line 6: 83
line 6: 92
line 9: 107
line 11: 110
line 6: 124
line 7: 135
StackMapTable: number_of_entries = 2
frame_type = 255 / full_frame /
offset_delta = 54
locals = [ class "[Ljava/lang/String;", class java/lang/Iterable, class java/lang/Iterable, class java/util/Collection, class java/util/Iterator, top, top, top, top, top, top, uninitialized 6, uninitialized 6, int ]
stack = []
frame_type = 55 / same /</init></init>
and after
public static final void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
Code:
stack=4, locals=6, args_size=1
0: aload_0
1: ldc #2 // String args
3: invokestatic #25 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V
6: new #17 // class test/a
9: dup
10: ldc #1 // String 1
12: invokestatic #24 // Method kotlin/collections/CollectionsKt.listOf:(Ljava/lang/Object;)Ljava/util/List;
15: checkcast #6 // class java/lang/Iterable
18: astore_0
19: astore 4
21: astore_3
22: aload_0
23: astore_1
24: new #10 // class java/util/ArrayList
27: dup
28: aload_0
29: bipush 10
31: invokestatic #23 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
34: invokespecial #22 // Method java/util/ArrayList."<init>":(I)V
37: checkcast #11 // class java/util/Collection
40: astore_0
41: aload_1
42: invokeinterface #27, 1 // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
47: astore_1
48: aload_1
49: invokeinterface #29, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
54: ifeq 94
57: aload_1
58: invokeinterface #30, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
63: astore_2
64: aload_0
65: aload_2
66: checkcast #8 // class java/lang/String
69: astore_2
70: astore 5
72: aload_2
73: dup
74: astore_2
75: invokestatic #20 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
78: invokestatic #21 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
81: astore_2
82: aload 5
84: aload_2
85: invokeinterface #28, 2 // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
90: pop
91: goto 48
94: aload_0
95: checkcast #13 // class java/util/List
98: astore 5
100: aload_3
101: aload 4
103: bipush 42
105: aload 5
107: invokespecial #26 // Method test/a."<init>":(ILjava/util/List;)V
110: astore_0
111: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;
114: aload_0
115: invokevirtual #19 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
118: return
StackMapTable: number_of_entries = 2
frame_type = 255 / full_frame /
offset_delta = 48
locals = [ class java/util/Collection, class java/util/Iterator, top, class test/a, class test/a ]
stack = []
frame_type = 255 / full_frame /
offset_delta = 45
locals = [ class java/util/Collection, top, top, class test/a, class test/a ]
stack = []</init></init>
Thanks for your report. ProGuard 6.0 beta1 is coming up in a few days, with some improvements to the preverification step. We'll have to check if this issue has been fixed.
Yes, it works with 6.0.3
Problem fixed in 6.0.3