okio
okio copied to clipboard
ProGuard cannot find all classes in release 3.4.0
I recently switched my Kotlin multiplatform project from okio 3.3.0 to 3.4.0. The code still works as before in the IDE and debug builds but when I then try to create a release build I get the following errors from ProGuard:
okio.AsyncTimeout$Watchdog: can't find referenced class java.lang.Thread$Builder$OfPlatform
okio.AsyncTimeout$Watchdog: can't find referenced class java.lang.Thread$Builder
okio.AsyncTimeout$Watchdog: can't find referenced class java.lang.Thread$Builder$OfVirtual
This is strange, because these classes do only exist as previews in Java Versions since 19 as far as I have seen and will only be made available in 21. So how can okio be depending on them and what could I do to circumvent this issue (besides not upgrading to 3.4.0)?
I am building with openjdk version "17.0.7" 2023-04-18 on macOS Ventura 13.4.1 and Kotlin 1.8.22
That’s curious. We don’t reference those APIs in AsyncTimeout.kt. I should download 3.4.0 to see if our release build references ’em.
javap -v okio/AsyncTimeout\$Watchdog.class
Classfile /Users/jwilson/Downloads/okio340/okio/AsyncTimeout$Watchdog.class
Last modified Feb. 1, 1980; size 2002 bytes
SHA-256 checksum 92b37fad05e65e94b4f153b33027ca6f16bfcdc113a9e77cc471c455516cf3b6
Compiled from "AsyncTimeout.kt"
final class okio.AsyncTimeout$Watchdog extends java.lang.Thread
minor version: 0
major version: 52
flags: (0x0030) ACC_FINAL, ACC_SUPER
this_class: #2 // okio/AsyncTimeout$Watchdog
super_class: #4 // java/lang/Thread
interfaces: 0, fields: 0, methods: 2, attributes: 3
Constant pool:
#1 = Utf8 okio/AsyncTimeout$Watchdog
#2 = Class #1 // okio/AsyncTimeout$Watchdog
#3 = Utf8 java/lang/Thread
#4 = Class #3 // java/lang/Thread
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Okio Watchdog
#8 = String #7 // Okio Watchdog
#9 = Utf8 (Ljava/lang/String;)V
#10 = NameAndType #5:#9 // "<init>":(Ljava/lang/String;)V
#11 = Methodref #4.#10 // java/lang/Thread."<init>":(Ljava/lang/String;)V
#12 = Utf8 setDaemon
#13 = Utf8 (Z)V
#14 = NameAndType #12:#13 // setDaemon:(Z)V
#15 = Methodref #2.#14 // okio/AsyncTimeout$Watchdog.setDaemon:(Z)V
#16 = Utf8 this
#17 = Utf8 Lokio/AsyncTimeout$Watchdog;
#18 = Utf8 run
#19 = Utf8 java/lang/InterruptedException
#20 = Class #19 // java/lang/InterruptedException
#21 = Utf8 okio/AsyncTimeout
#22 = Class #21 // okio/AsyncTimeout
#23 = Utf8 Companion
#24 = Utf8 Lokio/AsyncTimeout$Companion;
#25 = NameAndType #23:#24 // Companion:Lokio/AsyncTimeout$Companion;
#26 = Fieldref #22.#25 // okio/AsyncTimeout.Companion:Lokio/AsyncTimeout$Companion;
#27 = Utf8 okio/AsyncTimeout$Companion
#28 = Class #27 // okio/AsyncTimeout$Companion
#29 = Utf8 getLock
#30 = Utf8 ()Ljava/util/concurrent/locks/ReentrantLock;
#31 = NameAndType #29:#30 // getLock:()Ljava/util/concurrent/locks/ReentrantLock;
#32 = Methodref #28.#31 // okio/AsyncTimeout$Companion.getLock:()Ljava/util/concurrent/locks/ReentrantLock;
#33 = Utf8 java/util/concurrent/locks/Lock
#34 = Class #33 // java/util/concurrent/locks/Lock
#35 = Utf8 lock
#36 = NameAndType #35:#6 // lock:()V
#37 = InterfaceMethodref #34.#36 // java/util/concurrent/locks/Lock.lock:()V
#38 = Utf8 awaitTimeout$okio
#39 = Utf8 ()Lokio/AsyncTimeout;
#40 = NameAndType #38:#39 // awaitTimeout$okio:()Lokio/AsyncTimeout;
#41 = Methodref #28.#40 // okio/AsyncTimeout$Companion.awaitTimeout$okio:()Lokio/AsyncTimeout;
#42 = Utf8 access$getHead$cp
#43 = NameAndType #42:#39 // access$getHead$cp:()Lokio/AsyncTimeout;
#44 = Methodref #22.#43 // okio/AsyncTimeout.access$getHead$cp:()Lokio/AsyncTimeout;
#45 = Utf8 access$setHead$cp
#46 = Utf8 (Lokio/AsyncTimeout;)V
#47 = NameAndType #45:#46 // access$setHead$cp:(Lokio/AsyncTimeout;)V
#48 = Methodref #22.#47 // okio/AsyncTimeout.access$setHead$cp:(Lokio/AsyncTimeout;)V
#49 = Utf8 unlock
#50 = NameAndType #49:#6 // unlock:()V
#51 = InterfaceMethodref #34.#50 // java/util/concurrent/locks/Lock.unlock:()V
#52 = Utf8 kotlin/Unit
#53 = Class #52 // kotlin/Unit
#54 = Utf8 INSTANCE
#55 = Utf8 Lkotlin/Unit;
#56 = NameAndType #54:#55 // INSTANCE:Lkotlin/Unit;
#57 = Fieldref #53.#56 // kotlin/Unit.INSTANCE:Lkotlin/Unit;
#58 = Utf8 timedOut
#59 = NameAndType #58:#6 // timedOut:()V
#60 = Methodref #22.#59 // okio/AsyncTimeout.timedOut:()V
#61 = Utf8 $i$a$-withLock-AsyncTimeout$Watchdog$run$1
#62 = Utf8 I
#63 = Utf8 Ljava/lang/Object;
#64 = Utf8 java/lang/Throwable
#65 = Class #64 // java/lang/Throwable
#66 = Utf8 Lkotlin/Metadata;
#67 = Utf8 mv
#68 = Integer 1
#69 = Integer 8
#70 = Integer 0
#71 = Utf8 k
#72 = Utf8 xi
#73 = Integer 48
#74 = Utf8 d1
#75 = Utf8 \u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\b\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0000¢\u0006\u0002\u0010\u0002J\b\u0010\u0003\u001a\u00020\u0004H\u0016¨\u0006\u0005
#76 = Utf8 d2
#77 = Utf8 Ljava/lang/Thread;
#78 = Utf8
#79 = Utf8 okio
#80 = Utf8 Watchdog
#81 = Utf8 kotlin/jvm/internal/Ref$ObjectRef
#82 = Class #81 // kotlin/jvm/internal/Ref$ObjectRef
#83 = Utf8 kotlin/jvm/internal/Ref
#84 = Class #83 // kotlin/jvm/internal/Ref
#85 = Utf8 ObjectRef
#86 = Utf8 java/lang/Thread$State
#87 = Class #86 // java/lang/Thread$State
#88 = Utf8 State
#89 = Utf8 java/lang/Thread$UncaughtExceptionHandler
#90 = Class #89 // java/lang/Thread$UncaughtExceptionHandler
#91 = Utf8 UncaughtExceptionHandler
#92 = Utf8 java/lang/Thread$Builder$OfPlatform
#93 = Class #92 // java/lang/Thread$Builder$OfPlatform
#94 = Utf8 java/lang/Thread$Builder
#95 = Class #94 // java/lang/Thread$Builder
#96 = Utf8 OfPlatform
#97 = Utf8 Builder
#98 = Utf8 java/lang/Thread$Builder$OfVirtual
#99 = Class #98 // java/lang/Thread$Builder$OfVirtual
#100 = Utf8 OfVirtual
#101 = Utf8 AsyncTimeout.kt
#102 = Utf8 Code
#103 = Utf8 LineNumberTable
#104 = Utf8 LocalVariableTable
#105 = Utf8 StackMapTable
#106 = Utf8 InnerClasses
#107 = Utf8 SourceFile
#108 = Utf8 RuntimeVisibleAnnotations
{
public okio.AsyncTimeout$Watchdog();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: ldc #8 // String Okio Watchdog
3: invokespecial #11 // Method java/lang/Thread."<init>":(Ljava/lang/String;)V
6: nop
7: aload_0
8: iconst_1
9: invokevirtual #15 // Method setDaemon:(Z)V
12: nop
13: return
LineNumberTable:
line 176: 0
line 177: 6
line 178: 7
line 179: 12
line 176: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 this Lokio/AsyncTimeout$Watchdog;
public void run();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: nop
1: nop
2: aconst_null
3: astore_1
4: getstatic #26 // Field okio/AsyncTimeout.Companion:Lokio/AsyncTimeout$Companion;
7: invokevirtual #32 // Method okio/AsyncTimeout$Companion.getLock:()Ljava/util/concurrent/locks/ReentrantLock;
10: checkcast #34 // class java/util/concurrent/locks/Lock
13: astore_2
14: aload_2
15: invokeinterface #37, 1 // InterfaceMethod java/util/concurrent/locks/Lock.lock:()V
20: nop
21: iconst_0
22: istore_3
23: getstatic #26 // Field okio/AsyncTimeout.Companion:Lokio/AsyncTimeout$Companion;
26: invokevirtual #41 // Method okio/AsyncTimeout$Companion.awaitTimeout$okio:()Lokio/AsyncTimeout;
29: astore_1
30: aload_1
31: invokestatic #44 // Method okio/AsyncTimeout.access$getHead$cp:()Lokio/AsyncTimeout;
34: if_acmpne 53
37: getstatic #26 // Field okio/AsyncTimeout.Companion:Lokio/AsyncTimeout$Companion;
40: pop
41: aconst_null
42: invokestatic #48 // Method okio/AsyncTimeout.access$setHead$cp:(Lokio/AsyncTimeout;)V
45: nop
46: aload_2
47: invokeinterface #51, 1 // InterfaceMethod java/util/concurrent/locks/Lock.unlock:()V
52: return
53: nop
54: getstatic #57 // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
57: astore_3
58: aload_2
59: invokeinterface #51, 1 // InterfaceMethod java/util/concurrent/locks/Lock.unlock:()V
64: goto 76
67: astore_3
68: aload_2
69: invokeinterface #51, 1 // InterfaceMethod java/util/concurrent/locks/Lock.unlock:()V
74: aload_3
75: athrow
76: aload_1
77: dup
78: ifnull 87
81: invokevirtual #60 // Method okio/AsyncTimeout.timedOut:()V
84: goto 0
87: pop
88: goto 0
91: astore_1
92: goto 0
Exception table:
from to target type
20 46 67 any
53 58 67 any
67 68 67 any
1 88 91 Class java/lang/InterruptedException
StackMapTable: number_of_entries = 6
frame_type = 0 /* same */
frame_type = 254 /* append */
offset_delta = 52
locals = [ class okio/AsyncTimeout, class java/util/concurrent/locks/Lock, int ]
frame_type = 255 /* full_frame */
offset_delta = 13
locals = [ class okio/AsyncTimeout$Watchdog, class okio/AsyncTimeout, class java/util/concurrent/locks/Lock ]
stack = [ class java/lang/Throwable ]
frame_type = 252 /* append */
offset_delta = 8
locals = [ class kotlin/Unit ]
frame_type = 74 /* same_locals_1_stack_item */
stack = [ class okio/AsyncTimeout ]
frame_type = 255 /* full_frame */
offset_delta = 3
locals = [ class okio/AsyncTimeout$Watchdog ]
stack = [ class java/lang/InterruptedException ]
LineNumberTable:
line 182: 0
line 183: 1
line 184: 2
line 185: 4
line 186: 23
line 190: 30
line 191: 37
line 192: 45
line 194: 53
line 185: 57
line 197: 76
line 198: 91
LocalVariableTable:
Start Length Slot Name Signature
23 23 3 $i$a$-withLock-AsyncTimeout$Watchdog$run$1 I
53 1 3 $i$a$-withLock-AsyncTimeout$Watchdog$run$1 I
4 84 1 timedOut Ljava/lang/Object;
0 95 0 this Lokio/AsyncTimeout$Watchdog;
}
InnerClasses:
public static final #85= #82 of #84; // ObjectRef=class kotlin/jvm/internal/Ref$ObjectRef of class kotlin/jvm/internal/Ref
public static final #23= #28 of #22; // Companion=class okio/AsyncTimeout$Companion of class okio/AsyncTimeout
public static final #88= #87 of #4; // State=class java/lang/Thread$State of class java/lang/Thread
public static #91= #90 of #4; // UncaughtExceptionHandler=class java/lang/Thread$UncaughtExceptionHandler of class java/lang/Thread
public static #96= #93 of #95; // OfPlatform=class java/lang/Thread$Builder$OfPlatform of class java/lang/Thread$Builder
public static #97= #95 of #4; // Builder=class java/lang/Thread$Builder of class java/lang/Thread
public static #100= #99 of #95; // OfVirtual=class java/lang/Thread$Builder$OfVirtual of class java/lang/Thread$Builder
SourceFile: "AsyncTimeout.kt"
RuntimeVisibleAnnotations:
0: #66(#67=[I#68,I#69,I#70],#71=I#68,#72=I#73,#74=[s#75],#76=[s#17,s#77,s#6,s#18,s#78,s#79])
kotlin.Metadata(
mv=[1,8,0]
k=1
xi=48
d1=["\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0018\u0002\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\b\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0000¢\u0006\u0002\u0010\u0002J\b\u0010\u0003\u001a\u00020\u0004H\u0016¨\u0006\u0005"]
d2=["Lokio/AsyncTimeout$Watchdog;","Ljava/lang/Thread;","()V","run","","okio"]
)
I asked on the Kotlin slack.
It would probably help to build OKIO with a real JDK 17 or so.
Regarding the ProGuard side of this: ProGuard (and R8) typically require all the referenced classes to fully process & optimize applications. If classes are missing, ProGuard will warn about it because it might not be able to perform optimizations correctly. Classes come from your own code and third-party libraries embedded in your app (program classes, -injars) and library code such as the Java standard library classes (library classes, -libraryjars).
Typically you should provide all the missing classes but it can happen that a missing referenced class is OK: especially if it's a third-party library that references some class missing class but your app works fine normally, then it's probably OK for ProGuard to continue without the class.
You can ignore all warnings with -ignorewarnings (not recommended) or add -dontwarn options for specific classes. In this case:
-dontwarn okio.AsyncTimeout$Watchdog