Comments (13)
小伙子,找不到类这个问题跟 Gson 解析没有任何关系吧?类找不到是因为 ClassLoader 没有加载所在类的 dex 文件到 dex 数组中,这个问题大概率是在编译的过程中,出现问题的类没有编译进去导致的,你可以用 jadx 反编译核查一下。
from gsonfactory.
小伙子,找不到类这个问题跟 Gson 解析没有任何关系吧?类找不到是因为 ClassLoader 没有加载所在类的 dex 文件到 dex 数组中,这个问题大概率是在编译的过程中,出现问题的类没有编译进去导致的,你可以用 jadx 反编译核查一下。
使用Gson直接解析和8.0版本都是好的。主要还是混淆的问题,有些地方用的反射
from gsonfactory.
@rejigtian 小伙子,Kotlin data class 使用 Gson 和 GsonFactory 8.0 版本去解析都是有 Bug 的,看似能解析,但是存在较大的问题,具体有什么问题你可以回看一下版本更新记录,就算 8.0 的版本能解析,我不推荐你用。
from gsonfactory.
这边使用Demo复现了一下。
这里构造方法调用了反射,混淆后的类名是b.a.a.a,而这里反射继续调用fun (com.test.rejig.SimpleData2, kotlin.String): 就会出bug。
对应Kt代码
混淆后的代码
问题堆栈:
2024-04-11 11:01:14.221 14264-14264 AndroidRuntime com.hjq.gson.factory.demo E FATAL EXCEPTION: main Process: com.hjq.gson.factory.demo, PID: 14264 java.lang.RuntimeException: java.lang.reflect.InvocationTargetException at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:622) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963) Caused by: java.lang.ClassNotFoundException: Didn't find class "com.test.rejig.SimpleData2" on path: DexPathList[[zip file "/data/app/~~F9_ejQI75TeuaZlEL3kMlA==/com.hjq.gson.factory.demo-zFGm5So5coIS8ufehHFl8g==/base.apk"],nativeLibraryDirectories=[/data/app/~~F9_ejQI75TeuaZlEL3kMlA==/com.hjq.gson.factory.demo-zFGm5So5coIS8ufehHFl8g==/lib/arm64, /data/app/~~F9_ejQI75TeuaZlEL3kMlA==/com.hjq.gson.factory.demo-zFGm5So5coIS8ufehHFl8g==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:207) at java.lang.ClassLoader.loadClass(ClassLoader.java:379) at java.lang.ClassLoader.loadClass(ClassLoader.java:312) at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.parseType(:267) at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.loadParameterTypes(:258) at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findConstructorBySignature(:229) at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(:67) at kotlin.reflect.jvm.internal.KFunctionImpl$caller$2.invoke(:36) at kotlin.reflect.jvm.internal.ReflectProperties$LazyVal.invoke(:62) at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(:31) at kotlin.reflect.jvm.internal.KFunctionImpl.getCaller(Unknown Source:7) at kotlin.reflect.jvm.ReflectJvmMapping.getJavaMethod(:63) at kotlin.reflect.jvm.KCallablesJvm.setAccessible(:82) at com.hjq.gson.factory.constructor.KotlinDataClassDefaultValueConstructor.construct(:29) at com.hjq.gson.factory.constructor.ReflectCreatorConstructor.construct(:29) at com.hjq.gson.factory.element.ReflectiveTypeAdapter.read(:58) at com.google.gson.Gson.fromJson(:1227) at com.google.gson.Gson.fromJson(:1137) at com.google.gson.Gson.fromJson(:1047) at com.google.gson.Gson.fromJson(:982) at com.hjq.gson.factory.demo.MainActivity$1.onTitleClick(:31) at com.hjq.bar.TitleBar.onClick(:423) at android.view.View.performClick(View.java:7479) at android.widget.TextView.performClick(TextView.java:12296) at android.view.View.performClickInternal(View.java:7456) at android.view.View.access$3600(View.java:813) at android.view.View$PerformClick.run(View.java:28476) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:262) at android.app.ActivityThread.main(ActivityThread.java:8769) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)
from gsonfactory.
demo代码在这里,在demo基础上,新增了kt类和混淆规则
https://github.com/rejigtian/GsonFactory/tree/test-bug
from gsonfactory.
你这个是类找不到的异常,属于运行环境的问题,GsonFactory 是 Json 框架,不存在任何类加载的逻辑,除非你有直接的证据证明这个就是 GsonFactory 的问题,否则我将不会介入处理。
from gsonfactory.
这边看8.0的代码KotlinDataClassDefaultValueConstructor这个类中没有使用Kt的反射去构造,所以是正常的。
from gsonfactory.
@rejigtian 8.0 那种反射创建是存在缺陷的,并且无法解决,一旦 kotlin data class 在字段超过 32 个的情况下默认值不生效的问题,还有一些其他别的缺陷,也是没有办法解决的,框架是不可能回退回到之前那种方法去反射类的构造函数。
from gsonfactory.
这里是混淆,和类加载没关系。混淆后的类名变了,而通过Kt的反射去构造的方法中,还是使用的混淆前的类名,当然找不到对应的类。这里把Kt代码编译成字节码在反编译成Java代码,会发现里面确实是存在硬编码的。所以通过Kt反射去构造这个Kt的内部类,存在这个问题。
from gsonfactory.
`val rawTypeKotlin = rawType.kotlin
// 寻找 Kotlin 主构造函数,如果找不到就不往下执行
val constructor = rawTypeKotlin.primaryConstructor ?: return null
constructor.isAccessible = true`
这里直接这样调用混淆的类就有问题,也就是这个方案必须要要求数据类不被混淆,加入keep规则。
from gsonfactory.
小伙子,这个问题不是 Kotlin 官方提供的反射库有问题?你试一下 org.jetbrains.kotlin:kotlin-reflect
最新版本是否有这个问题,如果有的话反馈一下给 Kotlin 官方处理,临时的解决方案是先 Keep 对应的类。
from gsonfactory.
找了相关资料,确实用KClass反射,不能去混淆。
在Kotlin中使用KClass进行反射时,可能会遇到混淆(obfuscation)问题。如果你的Kotlin代码被混淆,反射将不能正确工作,因为混淆会改变类和函数的名称。为了解决这个问题,你需要在混淆配置文件中保护这些反射使用的类和方法不被混淆。
在你的proguard-rules.pro(如果你使用的是ProGuard作为混淆工具)文件中,你需要添加规则来保护这些反射使用的类。
from gsonfactory.
不过使用GsonFactory的开发者可能并不知道其内部实现是KClass的反射机制,因为Gson库本身的解析方案也没用这个,使用GsonFactory主要还是希望对Gson库有一些优化,既然有差异,可能踩坑。感觉可以在文档中写一下。
或者混淆规则中让开发者添加
-keepnames class com.test.rejig.** {
public (...);
}
把com.test.rejig替换成自己的包名
避免构造方法被混淆。
Kt的封装确实很好用,但是如果有更好的方案去实例化对象也能解决该问题
from gsonfactory.
Related Issues (20)
- 能否通过getDelegateAdapter方法给所有TypeAdapter都套层代理,出错时直接跳到下一个呢 HOT 8
- [疑惑]:关于readme写的为什么gson解析后,kotlin默认值无效的问题不太对 HOT 10
- [Bug]:com.google.gson.internal.ConstructorConstructor$9.construct (ConstructorConstructor.java:262) HOT 3
- [建议]:Gson 框架转义问题 HOT 2
- [疑惑]:<init> argument 4 has type int, got null, HOT 3
- [建议]:兼容类型不匹配的情况 HOT 33
- [建议]:我想去掉这样的警告打印<init> argument 4 has type int, got null HOT 7
- [疑惑]:GsonFactory反序列化数据量大时速度有点慢 HOT 10
- [疑惑]:9.0升级9.2 HOT 2
- [Bug]:9.0升级9.2 HOT 5
- [Bug]:升级到 9.3 直接无法解析 HOT 5
- [Bug]:从 9.0 升级 9.3 出现崩溃 HOT 21
- 9.0升级9.3[Bug]: HOT 1
- [Bug]:解析出现报错 HOT 4
- [疑惑]:为啥fastjson解析的是正常的,本框架解析的不一样 HOT 12
- 8.0版本 jitpack无法引用依赖 HOT 6
- [Bug]:开启混淆后,Kotlin的data class 内部类解析失败。 HOT 5
- [疑惑]:不知道怎么写标题,看描述吧 HOT 1
- [Bug]:result返回为空时出现java.lang.ClassCastException异常,具体返回格式看描述 HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gsonfactory.