You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Gradle、Kotlin及Java版本后Gson相关异常问题求助

升级Gradle、Kotlin和Java后Gson相关异常的解决方案

问题背景

将Gradle升级至8.2.1、Kotlin升级至1.9.21并切换到Java 17后,出现两类异常:

  1. java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to cj.a
  2. Exception while processing periodic Task TaskWrapper{task=class y6.g, processed=false} java.lang.NoSuchMethodException: y6.g.<init> [class android.content.Context, class u6.a]

自定义BaseModel代码如下:

import com.google.gson.Gson

abstract class BaseModel {

    inline fun <reified T: BaseModel> parseToJsonString(): String? {
        return try {
            parseToString<T>()
        } catch (e: Exception) {
            null
        }
    }

    inline fun <reified T: BaseModel> parseToString(): String {
        return Gson().toJson(this as T)
    }

    companion object {

        inline fun <reified T: BaseModel> fromJsonString(json: String): T? {
            return try {
                decodeFromString(json)
            } catch (e: Exception) {
                null
            }
        }

        inline fun <reified T: BaseModel> decodeFromString(json: String): T {
            return Gson().fromJson(json, T::class.java)
        }

    }
}

已尝试添加以下ProGuard规则但问题未解决:

##---------------Begin: proguard configuration for Gson  ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
#-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }

-keep class com.google.** { *; }

-keep class sun.misc.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }

-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

-keep class * implements com.google.gson.*

##---------------End: proguard configuration for Gson  ----------

原因分析

1. ClassCastException(LinkedTreeMap转自定义Model失败)

  • 升级后ProGuard/R8的混淆规则生效更严格,自定义Model类被混淆后,Gson无法正确识别类结构,反序列化时只能用默认的LinkedTreeMap存储数据,导致类型转换失败。
  • 现有ProGuard规则仅保留了Gson示例类和Gson相关接口实现,未保留项目中所有继承BaseModel的实体类,这是核心问题。
  • Java 17的反射限制更严格,即使类未被完全混淆,反射获取类信息时也可能受限。

2. NoSuchMethodException(构造方法找不到)

  • 混淆后的y6.g类对应的原始类,其带Context和u6.a参数的构造方法被ProGuard/R8移除或重命名。
  • 周期性任务通过反射调用该构造方法,但混淆规则未保留该构造方法的签名。

解决方案

针对ClassCastException的修复

  1. 修改ProGuard规则,保留所有BaseModel子类
    在Gson混淆规则块中添加:
# 保留所有继承BaseModel的实体类及其字段、构造方法
-keep public class * extends your.package.name.BaseModel {
    <fields>;
    <init>(...);
}

注意替换your.package.name为BaseModel实际所在的包路径。

  1. 优化BaseModel的Gson使用方式
    避免每次序列化/反序列化都创建新的Gson实例,全局复用一个Gson对象,减少性能开销和潜在类加载问题:
import com.google.gson.Gson

abstract class BaseModel {

    inline fun <reified T: BaseModel> parseToJsonString(): String? {
        return try {
            Companion.gson.toJson(this as T)
        } catch (e: Exception) {
            null
        }
    }

    companion object {
        private val gson = Gson()

        inline fun <reified T: BaseModel> fromJsonString(json: String): T? {
            return try {
                gson.fromJson(json, T::class.java)
            } catch (e: Exception) {
                null
            }
        }
    }
}

针对NoSuchMethodException的修复

  1. 保留目标类的特定构造方法
    通过混淆映射文件mapping.txt(位于build/outputs/mapping/release/目录)查找y6.g对应的原始类,然后在ProGuard规则中添加:
# 保留原始类的带Context和对应参数类的构造方法
-keep class your.package.name.OriginalTaskClass {
    <init>(android.content.Context, your.package.name.OriginalU6AClass);
}

替换your.package.name.OriginalTaskClass和your.package.name.OriginalU6AClass为实际类路径。

  1. 无法定位原始类时的兜底方案
    如果找不到具体类,可尝试保留所有周期性任务相关类:
# 假设周期性任务类都在特定包下
-keep class your.package.name.tasks.** {
    <init>(...);
    <methods>;
}

适配Java 17的额外配置

在gradle.properties中添加:

android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath=true
android.enableR8.fullMode=false

关闭R8全模式可减少严格的代码移除,避免反射相关问题。


内容的提问来源于stack exchange,提问作者user21300258

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:32:49