pilgr/Paper

IllegalAccessException since AGP 7.0.2 everytime when Paper.book().read(key, defaultValue) is called after Paper.book().write(key, value)

Vall0n opened this issue ยท 9 comments

Hey @pilgr,

first of all thanks for the great library!
But I found an issue which breaks my app after upgrading 'com.android.tools.build gradle (agp) to 7.0.2. It is working with agp 7.0.1, so maybe it's not this library but one of the fixes of agp 7.0.2... See agp 7.0.2 changes especially Desugaring and reproducible builds

Or maybe even in the Kryo, kryo-serializers or objenesis libraries... Which actually are not up to date, which maybe causes the issue here. But I'am just guessing.. ๐Ÿ˜…

Steps to reproduce

  • Checkout master branch
  • extract and apply attached patch (use agp 7.0.2, target sdk 30 and moved models in own package) AGP_702_breaks_Book_read()_after_write.patch.zip
  • Run Paper sample app
  • Click on "write"
  • click on "read"
    -> App will crash with following stacktrace
2021-09-07 12:25:56.147 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden method Lsun/nio/ch/DirectBuffer;->cleaner()Lsun/misc/Cleaner; (greylist, linking, allowed)
2021-09-07 12:25:56.147 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden method Lsun/misc/Cleaner;->clean()V (greylist,core-platform-api, linking, allowed)
2021-09-07 12:25:56.154 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden field Ljava/util/Arrays$ArrayList;->a:[Ljava/lang/Object; (greylist, reflection, allowed)
2021-09-07 12:25:56.154 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden field Ljava/util/Collections$UnmodifiableCollection;->c:Ljava/util/Collection; (greylist, reflection, allowed)
2021-09-07 12:25:56.154 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden field Ljava/util/Collections$UnmodifiableMap;->m:Ljava/util/Map; (greylist, reflection, allowed)
2021-09-07 12:25:56.157 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden field Ljava/util/Collections$SynchronizedCollection;->c:Ljava/util/Collection; (greylist, reflection, allowed)
2021-09-07 12:25:56.157 7132-7177/paperdb.io.paperdb W/erdb.io.paperd: Accessing hidden field Ljava/util/Collections$SynchronizedMap;->m:Ljava/util/Map; (greylist, reflection, allowed)
2021-09-07 12:25:56.163 7132-7177/paperdb.io.paperdb E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: paperdb.io.paperdb, PID: 7132
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$4.done(AsyncTask.java:415)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
     Caused by: io.paperdb.PaperDbException: Couldn't read/deserialize file /data/user/0/paperdb.io.paperdb/files/io.paperdb/o1.pt for table o1
        at io.paperdb.DbStoragePlainFile.readTableFile(:323)
        at io.paperdb.DbStoragePlainFile.select(:166)
        at io.paperdb.Book.read(:73)
        at paperdb.io.paperdb.MainActivity$e.a(:131)
        at paperdb.io.paperdb.MainActivity$e.doInBackground(:120)
        at android.os.AsyncTask$3.call(AsyncTask.java:394)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641at java.lang.Thread.run(Thread.java:923Caused by: com.esotericsoftware.kryo.KryoException: Error constructing instance of class: io.paperdb.PaperTable
        at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy$2.newInstance(:1300)
        at com.esotericsoftware.kryo.Kryo.newInstance(:1139)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.create(:562)
        at com.esotericsoftware.kryo.serializers.FieldSerializer.read(:538)
        at com.esotericsoftware.kryo.Kryo.readObject(:712)
        at io.paperdb.DbStoragePlainFile.readContent(:332)
        at io.paperdb.DbStoragePlainFile.readTableFile(:316)
        at io.paperdb.DbStoragePlainFile.select(:166at io.paperdb.Book.read(:73at paperdb.io.paperdb.MainActivity$e.a(:131at paperdb.io.paperdb.MainActivity$e.doInBackground(:120at android.os.AsyncTask$3.call(AsyncTask.java:394at java.util.concurrent.FutureTask.run(FutureTask.java:266at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641at java.lang.Thread.run(Thread.java:923Caused by: java.lang.IllegalAccessException: java.lang.Class<io.paperdb.PaperTable> is not accessible from java.lang.Class<com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy$2>
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy$2.newInstance(:1298)
        at com.esotericsoftware.kryo.Kryo.newInstance(:1139at com.esotericsoftware.kryo.serializers.FieldSerializer.create(:562at com.esotericsoftware.kryo.serializers.FieldSerializer.read(:538at com.esotericsoftware.kryo.Kryo.readObject(:712at io.paperdb.DbStoragePlainFile.readContent(:332at io.paperdb.DbStoragePlainFile.readTableFile(:316at io.paperdb.DbStoragePlainFile.select(:166at io.paperdb.Book.read(:73at paperdb.io.paperdb.MainActivity$e.a(:131at paperdb.io.paperdb.MainActivity$e.doInBackground(:120at android.os.AsyncTask$3.call(AsyncTask.java:394at java.util.concurrent.FutureTask.run(FutureTask.java:266at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641at java.lang.Thread.run(Thread.java:923

If I can support to fix this issue just let me know or if any information is missing.

Best regards,

Josef

pilgr commented

Thanks for very detailed report. It looks very weird and seems like an issue/limitation in AGP. Anyway I'll keep an eye on it.

Hey, I'm having a similar issue starting from using AGP 7.0.2. Looks like R8 / ProGuard is removing some classes and causing errors.

I'm also experiencing this issue as described.

class PaperTable --------> public class PaperTable

This still happens with AGP 7.0.3. Which contains following changes.

I also tried the sugessetd fix from @TJHello (thanks for that!) to make the class public but it doesn't work sadly.

@pilgr can you prioritize this fix please? I can confirm it's still happening on 7.0.3 AGP version, 7.0.0 is OK though

It looks like this is an R8 issue. If the -allowaccessmodification flag is present in proguard rules. It changes access of the default constructor to public, but keeps the class PaperTable internal:

# direct methods
.method public constructor <init>()V
    .registers 1

    .line 6
    .local p0, "this":Lio/paperdb/PaperTable;, "Lio/paperdb/PaperTable<TT;>;"
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    .line 7
    return-void
.end method

And it doesn't allow to create instance into the Kryo library.
It helped me to make the default constructor private, this does not allow R8 to change access.
Making class public helped me also.

Is this issue fixed now?

pilgr commented

Hey folks, sorry for keeping you waiting for the fix for such a long time. The good news โ€“ we have the new fixed version to try out. Please refer to this task for instructions and give your feedback #196