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

com.google.gson.JsonIOException: Abstract classes can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. #2379

Open
4 tasks
maheshordex opened this issue Apr 24, 2023 · 33 comments
Labels
bug proguard-r8 Issues relating to the use of ProGuard and/or R8, such as problems due to obfuscation

Comments

@maheshordex
Copy link

Gson version

'2.10.1'

Java / Android version

JDK 17
Android Android Studio Flamingo | 2022.2.1

Used tools

  • Maven; version:
  • Gradle; version:
  • ProGuard (attach the configuration file please); version:
  • ...

Description

When we convert json string to Model class it gives error related to adapter. I just updated android studio to latest version it works in older version.

Expected behavior

It should convert json string to Model class.

Actual behavior

It throws an error.

Reproduction steps

  1. ...
  2. ...

Exception stack trace

W  com.google.gson.JsonIOException: Abstract classes can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Class name: com.xxx.xxx.data.pojo.other.GeneralResponse
2023-04-24 16:30:49.897 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:136)
2023-04-24 16:30:49.897 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.createAccumulator(ReflectiveTypeAdapterFactory.java:427)
2023-04-24 16:30:49.897 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:383)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.Gson.fromJson(Gson.java:1227)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.Gson.fromJson(Gson.java:1137)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.Gson.fromJson(Gson.java:1047)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.google.gson.Gson.fromJson(Gson.java:982)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.xxx.xxx.data.repository.BaseRepository.checkSuccess(BaseRepository.kt:8)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.xxx.xxx.data.repository.ApiRepository.login(ApiRepository.kt:51)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at com.xxx.xxx.data.repository.ApiRepository$login$1.invokeSuspend(ApiRepository.kt:0)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
2023-04-24 16:30:49.898 23084-23084 System.err              com.xxx.xxx                  W  	at android.os.Handler.handleCallback(Handler.java:938)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at android.os.Handler.dispatchMessage(Handler.java:99)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at android.os.Looper.loop(Looper.java:223)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at android.app.ActivityThread.main(ActivityThread.java:7656)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at java.lang.reflect.Method.invoke(Native Method)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
2023-04-24 16:30:49.899 23084-23084 System.err              com.xxx.xxx                  W  	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
@Marcono1234
Copy link
Collaborator

I just updated android studio to latest version it works in older version.

Have you also updated Gson, or is the Gson version the same?

Is GeneralResponse actually an abstract class? And if so, have you registered a TypeAdapter (or JsonDeserializer) for it? If not it is a bit surprising that this exception did not occur before.

Could you please try to create a minimal, reproducible example?

@SearchDream
Copy link

I think this issue was caused by the latest update of gradle (8.0), which by default is R8 full mode.

@maheshordex
Copy link
Author

Marcono1234: I have updated latest gson version 2.10.1
SearchDream : May be possible as it is working in old gradle and old android studio

@maheshordex
Copy link
Author

Please check for JDK 17 support

@SearchDream
Copy link

I add "android.enableR8.fullMode=false" on gradle.properties and the error was gone.

@cdiazc
Copy link

cdiazc commented Apr 25, 2023

@SearchDream Same here, adding the line got rid of the exact same error. Thank you !

@maheshordex
Copy link
Author

maheshordex commented Apr 25, 2023

@SearchDream @cdiazc
If I added android.enableR8.fullMode=false it shows below error

Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in D:****\app\build\outputs\mapping\release\missing_rules.txt.

@SearchDream
Copy link

@pandelisgreen13
Copy link

I have the same error with R8 (full mode) when I updated the AGP to version 8.0

@maheshordex
Copy link
Author

@pandelisgreen13 did you got any solution for it ?
I am still searching for solution

@kzotin
Copy link

kzotin commented May 2, 2023

First applied recommendations from here, though they didn't help.

What helped is replacing

-keepclassmembers,allowobfuscation class * {
 @com.google.gson.annotations.SerializedName <fields>;
}

with

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

@maheshordex
Copy link
Author

@kzotin
Thanks for update for me I need to add all below lines.

-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}
-keepnames class com.fasterxml.jackson.databind.** { *; }
-dontwarn com.fasterxml.jackson.databind.**

@jaison043
Copy link

Same issue for here too on release builds. The above mentioned fixes didn't worked . What worked was switch back to Gradle 7.5 for now.

@maheshordex
Copy link
Author

@jaison043
I think you can try after remove below code

-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName ;
}

@JuanchiFraga
Copy link

The previously mentioned rules didn't work in my project. With the arrival of AGP 8.0 and Android Studio Flamingo, the rule that solved my problem was

-if class *
-keepclasseswithmembers class <1> {
    <init>(...);
    @com.google.gson.annotations.SerializedName <fields>;
}

@Marcono1234
Copy link
Collaborator

We have added a section to the Troubleshooting Guide which hopefully helps with this:

JsonIOException: 'Abstract classes can't be instantiated!' (R8)

Could you please check if the entry is useful for you or if we should improve it in any way?

@kzotin's suggestion in #2379 (comment) might work as well, but in the R8 integration tests I added it appears R8 then just does not make the class abstract anymore but might still remove all constructors. So you will be dependent on JDK Unsafe then to create instances of the class (see also GsonBuilder.disableJdkUnsafe()). Would be good if someone could verify this by checking if using disableJdkUnsafe() will then throw a different exception saying "Unable to create instance of ...".

@captainepoch
Copy link

The previously mentioned rules didn't work in my project. With the arrival of AGP 8.0 and Android Studio Flamingo, the rule that solved my problem was

-if class *
-keepclasseswithmembers class <1> {
    <init>(...);
    @com.google.gson.annotations.SerializedName <fields>;
}

This rule worked perfectly for me, thanks!

@randauto
Copy link

@kzotin Thanks for update for me I need to add all below lines.

-keepclassmembers,allowobfuscation class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}
-keepnames class com.fasterxml.jackson.databind.** { *; }
-dontwarn com.fasterxml.jackson.databind.**

It's worked for me, thanks!

@gemeauxph
Copy link

gemeauxph commented Jul 29, 2023

Side note: If not using the @SerializedName annotation, using:

-keep class * { @com.google.gson.annotations.SerializedName <fields>; }

will remove the error but not fix the issue since data object members will still be null. So you need to add:

-keepclassmembers class MyDataClass { !transient <fields>; }

simply replace MyDataClass with your data class, this is mentioned here R8 FAQ

In my case, I had to include both.

@jasonrobinson-gpsw
Copy link

This worked for us:

-if class * {
  @com.google.gson.annotations.SerializedName *** *;
}
-keepclassmembers,allowobfuscation class <1> {
  <init>();
  @com.google.gson.annotations.SerializedName <fields>;
}

It will only work though if you're deserializing a class that has at least 1 field annotated with @SerializedName. In that case, you'll either have to annotate the class with @Keep or add a rule specific to that class that retains its empty constructor.

@coinzdude
Copy link

coinzdude commented Aug 27, 2023

The previously mentioned rules didn't work in my project. With the arrival of AGP 8.0 and Android Studio Flamingo, the rule that solved my problem was

-if class *
-keepclasseswithmembers class <1> {
    <init>(...);
    @com.google.gson.annotations.SerializedName <fields>;
}

This worked for me as well. debug build works fine, release did not. I put that rule at the end of my proguard-rules.pro file

gradle:8.1.0-alpha05

                    val gson = Gson()
                    val document = gson.fromJson(response, Document::class.java) // This is the line that would crash

not sure if needed, but I decorated all my anonymous class properties too

    data class Document(
        @SerializedName("items") val items: List<Item>
    )

data class Item(
        @SerializedName("deviceId") val deviceId: String,
        @SerializedName("name") val name: String,
        @SerializedName("label") val label: String,
        @SerializedName("components") val components: List<Component>
    )

@Shvet
Copy link

Shvet commented Oct 10, 2023

First applied recommendations from here, though they didn't help.

What helped is replacing

-keepclassmembers,allowobfuscation class * {
 @com.google.gson.annotations.SerializedName <fields>;
}

with

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

any update for R8 issue? In some projects, This solution works and in some other projects, it does not.

@Marcono1234
Copy link
Collaborator

In some projects, This solution works and in some other projects, it does not.

@Shvet, could you please provide some more information? Are the projects where this does not work also consistently using @SerializedName on all of their fields? And are you talking about this specific "Abstract classes can't be instantiated!" issue, or some other issues with R8 (e.g. incorrect JSON, missing field values, other exceptions...)?

@jaydeepbhayani
Copy link

The previously mentioned rules didn't work in my project. With the arrival of AGP 8.0 and Android Studio Flamingo, the rule that solved my problem was

-if class *
-keepclasseswithmembers class <1> {
    <init>(...);
    @com.google.gson.annotations.SerializedName <fields>;
}

This worked for me as well. debug build works fine, release did not. I put that rule at the end of my proguard-rules.pro file

gradle:8.1.0-alpha05

                    val gson = Gson()
                    val document = gson.fromJson(response, Document::class.java) // This is the line that would crash

not sure if needed, but I decorated all my anonymous class properties too

    data class Document(
        @SerializedName("items") val items: List<Item>
    )

data class Item(
        @SerializedName("deviceId") val deviceId: String,
        @SerializedName("name") val name: String,
        @SerializedName("label") val label: String,
        @SerializedName("components") val components: List<Component>
    )

For gradle 8.0 with Android Studio Giraffe | 2022.3.1 Patch 2 worked for me

OR

android.enableR8.fullMode=false add this to gradle.properties.

@gerardoeg
Copy link

First applied recommendations from here, though they didn't help.

What helped is replacing

-keepclassmembers,allowobfuscation class * {
 @com.google.gson.annotations.SerializedName <fields>;
}

with

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

This worked with AGP 8.0 with the defaults in android.enableR8.fullMode

@Shvet
Copy link

Shvet commented Oct 27, 2023

In some projects, This solution works and in some other projects, it does not.

@Shvet, could you please provide some more information? Are the projects where this does not work also consistently using @SerializedName on all of their fields? And are you talking about this specific "Abstract classes can't be instantiated!" issue, or some other issues with R8 (e.g. incorrect JSON, missing field values, other exceptions...)?

@Marcono1234 Sorry for late reply, I am talking about only "Abstract classes can't be instantiated". AS for more infomation I can not send you sample code as I can not upload them for public.

@n-abdelmaksoud
Copy link

n-abdelmaksoud commented Nov 14, 2023

-keep class com.google.gson.reflect.TypeToken { *; }

-keep class * extends com.google.gson.reflect.TypeToken

This helped me to fix the issue. Hope it helps someone after staying the whole day trying several solutions.

@akardas16
Copy link

above methods didn't work for me.

Process: com.akardas16.chatgpt, PID: 20654 com.google.gson.JsonIOException: Abstract classes can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Class name: android.graphics.drawable.Drawable at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:136) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.createAccumulator(ReflectiveTypeAdapterFactory.java:427) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:383) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at com.google.gson.Gson.fromJson(Gson.java:1227) at com.google.gson.Gson.fromJson(Gson.java:1137) at com.google.gson.Gson.fromJson(Gson.java:1047) at com.google.gson.Gson.fromJson(Gson.java:1014) at com.akardas16.chatgpt.roomdatabase.ConverterDrawableList.toDrawables(RoomDataModel.kt:45) at com.akardas16.chatgpt.roomdatabase.DaoInterface_Impl.getAllItems(DaoInterface_Impl.java:217) at com.akardas16.chatgpt.tabscreens.HomeTabKt$HomeTab$1$1.invokeSuspend(HomeTab.kt:172) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108) at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@4560aab, androidx.compose.runtime.BroadcastFrameClock@b24d508, StandaloneCoroutine{Cancelling}@3c754a1, Dispatchers.IO]

@Marcono1234
Copy link
Collaborator

@akardas16, what you are experiencing seems to be unrelated to this R8 issue.

According to the exception, you are trying to deserialize android.graphics.drawable.Drawable, which is indeed abstract, so the exception is correct. And also in general you should not (implicitly) use Gson's reflection-based adapter for third party classes, such as Android library classes. Because you will then depend on the internals of these classes which could differ between Android versions (possibly even between Android devices). Instead exclude the field of type Drawable in case you did not want to deserialize it in the first place, or write a custom TypeAdapter. If you have any questions regarding this, it might be best to ask them on Stack Overflow, to not move this issue here too far off-topic.

@danatechgithub4
Copy link

This is normal
image

This is R8
image

R8 changed all data class that have not been instantiated into abstract classes, f--k!

image

-if class * -keepclasseswithmembers class <1> { <init>(...); @com.google.gson.annotations.SerializedName <fields>; }
solved my problem

@raquezha
Copy link

The previously mentioned rules didn't work in my project. With the arrival of AGP 8.0 and Android Studio Flamingo, the rule that solved my problem was

-if class *
-keepclasseswithmembers class <1> {
    <init>(...);
    @com.google.gson.annotations.SerializedName <fields>;
}

This worked for me thanks!

@joknu1
Copy link

joknu1 commented Feb 6, 2024

Having to add

-keep class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

when setting fullMode=true, made apk size bigger than if removing the rule, and build with fullMode=false. 🚀

@Marcono1234 Marcono1234 added the proguard-r8 Issues relating to the use of ProGuard and/or R8, such as problems due to obfuscation label Mar 29, 2024
@wh173d3v11
Copy link

wh173d3v11 commented Apr 21, 2024

In My case, I have used @keep annotation for data classes, but the import was wrong com.google.errorprone.annotations.Keep🤕

It should Import - androidx.annotation.Keep 🤩

Additionally i already have these in my proguard rules.

#Gson
-keepattributes Signature
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken

This solved my issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug proguard-r8 Issues relating to the use of ProGuard and/or R8, such as problems due to obfuscation
Projects
None yet
Development

No branches or pull requests