Android 6.0调用JGroups 4.1.6.Final的JChannel出现NoClassDefFoundError问题排查
遇到的问题
我最近在Android项目里用JGroups 4.1.6.Final做组播通信,在Activity里初始化JChannel的代码很简单:
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) JChannel() } }
奇怪的是,这个APK在Android 8.0上跑完全没问题,但一放到Android 6.0的设备上就直接崩了,报错日志是这样的:
10-18 14:11:43.148 4633 4633 E AndroidRuntime: FATAL EXCEPTION: main
10-18 14:11:43.148 4633 4633 E AndroidRuntime: Process: com.horph.jbomb, PID: 4633
10-18 14:11:43.148 4633 4633 E AndroidRuntime: java.lang.NoClassDefFoundError: org.jgroups.-$$Lambda$CbeKW6_ggTAEDuiYP5MNn0HcZP8
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at org.jgroups.JChannel.init(JChannel.java:950)
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at org.jgroups.JChannel.<init>(JChannel.java:125)
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at org.jgroups.JChannel.<init>(JChannel.java:107)
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at org.jgroups.JChannel.<init>(JChannel.java:98)
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at com.horph.jbomb.MainActivity.onCreate(MainActivity.kt:10)
10-18 14:11:43.148 4633 4633 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:6237)
问题根源
其实这个坑是Android版本对Java 8特性支持的差异导致的:
- Android 8.0(API 26)及以上的ART虚拟机已经原生支持Java 8的Lambda表达式,编译器会把Lambda编译成
-$$Lambda$开头的动态类,系统能正常加载这些类。 - 但Android 6.0(API 23)及更低版本的ART虚拟机不支持这种动态生成Lambda类的方式,当JGroups内部的代码尝试使用Lambda时,系统找不到对应的类,就抛出了
NoClassDefFoundError。
另外如果你的项目开了ProGuard代码混淆,要是没给JGroups配置正确的混淆规则,把这些Lambda相关的类给混淆掉了,也会触发同样的错误,但核心原因还是老版本Android对Java 8 Lambda的支持不足。
内容的提问来源于stack exchange,提问作者Allen Luce

