Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProGuard cannot find all classes in release 3.4.0 #1298

Open
mipastgt opened this issue Jul 20, 2023 · 5 comments
Open

ProGuard cannot find all classes in release 3.4.0 #1298

mipastgt opened this issue Jul 20, 2023 · 5 comments

Comments

@mipastgt
Copy link

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

@swankjesse
Copy link
Member

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.

@swankjesse
Copy link
Member

swankjesse commented Jul 20, 2023

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"]
    )

@swankjesse
Copy link
Member

I asked on the Kotlin slack.

@mipastgt
Copy link
Author

mipastgt commented Jul 26, 2023

It would probably help to build OKIO with a real JDK 17 or so.

@mrjameshamilton
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants