Android 出现java.lang.NoClassDefFoundError错误的一种解决方案

本文介绍了解决Android开发中遇到的NoClassDefFoundError问题的方法,主要针对5.0以下系统的兼容性问题,通过启用MultiDex并配置相关依赖来解决方法数量超过65535限制的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://blog.youkuaiyun.com/sayid_des/article/details/50462261

今天在Android开发时候,遇到奇怪的问题。相同的程序,运行在一部分手机上没有问题。运行到另外个别手机上总是出现以下错误:

 Process: com.yijiaoxing.organizationsss, PID: 22705
                                                                                java.lang.NoClassDefFoundError: org.apache.commons.collections.map.UnmodifiableMap
                                                                                    at org.apache.commons.collections.MapUtils.<clinit>(MapUtils.java:96)
                                                                                    at com.yijiaoxing.organization.ui.TuijianFragment.initFragment(TuijianFragment.java:219)
                                                                                    at com.yijiaoxing.organization.ui.TuijianFragment.setChangelView(TuijianFragment.java:96)
                                                                                    at com.yijiaoxing.organization.ui.TuijianFragment.initSetData(TuijianFragment.java:257)
                                                                                    at net.tycmc.bulb.bases.ui.BaseFragment.onCreateView(BaseFragment.java:32)
                                                                                    at android.support.v4.app.Fragment.performCreateView(Fragment.java:2087)
                                                                                    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1113)
                                                                                    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295)
                                                                                    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
                                                                                    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682)
                                                                                    at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
                                                                                    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:607)
                                                                                    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
                                                                                    at android.app.Activity.performStart(Activity.java:5259)
                                                                                    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2174)
                                                                                    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2250)
                                                                                    at android.app.ActivityThread.access$900(ActivityThread.java:141)
                                                                                    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1213)
                                                                                    at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                    at android.os.Looper.loop(Looper.java:136)
                                                                                    at android.app.ActivityThread.main(ActivityThread.java:5072)
                                                                                    at java.lang.reflect.Method.invokeNative(Native Method)
                                                                                    at java.lang.reflect.Method.invoke(Method.java:515)
                                                                                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
                                                                                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
                                                                                    at dalvik.system.NativeStart.main(Native Method)

查找了好久,总是也无法解决。后来查到解决办法是:

由于build.gradle文件里已经声明了 multiDexEnabled true 。可以解决65535无法运行问题。(声明原因:当你的程序达到65535个的时候,程序将运行不起来了。不太好处理。这也是好多人从eclipse 转到 Studio的其中一个原因 )当方法数超过65535时便会自动打出两个Dex包命名为 classes.dex classes2.dex ,一些方法被打入了第二个dex包,即classes2.dex中,导致了5.0以下机型无法运行应用报错。

下面是解决方案:

1.在defaultConfig 中已经声明 multiDexEnabled true 用于启用MultiDex

2.在依赖中添加 compile 'com.android.support:multidex:1.0.1' 支持包用于5.0以下系统

3.如果你的工程中已经含有Application类,那么让它继承android.support.multidex.MultiDexApplication类,如果你的Application已经继承了其他类并且不想做改动,那么还有另外一种使用方式,覆写attachBaseContext()方法:

public class MyApplication extends FooApplication {
        @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7





<think>我们正在解决一个具体的NoClassDefFoundError错误错误信息指向了系统内部类`com.android.server.wm.SrWindowManagerService`。结合引用和之前的回答,我们需要深入分析原因并提供解决方案。引用[1]提到NoClassDefFoundError可能由类路径问题、编译错误、类加载问题、缺失依赖项和版本冲突引起。引用[2]指出可能的原因包括静态变量加载失败以及工程中未正确添加jar包(对于Maven项目需要检查依赖)。引用[3]描述了错误的表现形式。引用[4]则区分了NoClassDefFoundError和ClassNotFoundException,强调前者通常意味着类在编译时存在但运行时在类路径中找不到。针对当前错误,由于`SrWindowManagerService`是Android系统内部类,普通应用无法直接访问,因此最可能的原因是:1.应用尝试通过反射等方式调用了系统内部API(非公开API)。2.依赖的某个库使用了系统内部API,导致在运行时找不到该类。3.混淆配置问题导致该类被移除(但系统内部类通常不在应用代码中,所以这种情况较少见,除非是系统应用开发)。解决方案:1.**避免使用非公开API**:普通应用不应使用系统内部类,应使用公开的API替代。例如,如果需要窗口管理服务,应使用`WindowManager`,通过`Context.getSystemService(Context.WINDOW_SERVICE)`获取。2.**检查依赖库**:如果使用了第三方库,检查该库是否有使用系统内部API的情况。如果有,考虑寻找替代库或联系库作者更新。3.**系统应用开发特殊处理**:如果是系统应用(拥有系统签名),需要确保在编译时包含系统jar包(如framework.jar),并在proguard规则中保留该类。-在build.gradle中添加依赖(仅编译时):```gradledependencies{compileOnlyfiles('libs/framework.jar')//系统jar包路径}```-在proguard规则中保留:```proguard-keepclasscom.android.server.wm.SrWindowManagerService{*;}-dontwarncom.android.server.wm.**```4.**运行时检查**:如果必须使用反射,应在调用前检查类是否存在:```javatry{Class.forName("com.android.server.wm.SrWindowManagerService");//继续反射调用}catch(ClassNotFoundExceptione){//处理类不存在的情况,使用备选方案}```重要提示:GooglePlay禁止普通应用使用非公开API,因此上架的应用必须避免使用系统内部类。§§相关问题§§1.如何检测代码中是否使用了非公开API?2.系统应用和普通应用在开发上有何不同?3.如何正确配置ProGuard以避免类被移除?4.反射调用系统内部API有哪些风险?</think>### `java.lang.NoClassDefFoundError` 原因分析与解决方法 #### **错误本质** `NoClassDefFoundError` 表示 **编译时存在的类在运行时缺失**,不同于`ClassNotFoundException`(编译时就不存在)[^4]。核心是 JVM 在运行时无法加载已编译的类。 #### **常见原因** 1. **类路径配置错误**(最常见) - 依赖库未正确添加到 classpath - Maven/Gradle 依赖作用域错误(如 `test` 依赖用于主代码) - IDE 未同步构建路径(如 Eclipse 中 `.classpath` 文件异常) 2. **类加载冲突** - 多个 ClassLoader 加载同一类导致冲突 - 动态加载机制(如 OSGi)未正确处理依赖 3. **静态初始化失败** ```java public class BrokenClass { static int data = 1 / 0; // 静态块异常会导致NoClassDefFoundError } ``` 当其他类引用 `BrokenClass` 时触发错误[^2] 4. **打包问题** - WAR/JAR 文件中遗漏类文件 - ProGuard/R8 过度优化移除了"看似未使用"的类 - 多模块项目中子模块未正确打包 5. **Android 特有原因** - 系统内部类访问(如 `SrWindowManagerService`) - 未声明 `uses-library` 的 Android 系统库 - 跨 DEX 文件类引用错误(Multidex 配置问题) --- ### **系统化解决方案** #### **步骤 1:验证类路径** - **Maven 项目**: ```xml <!-- 检查依赖是否在正确作用域 --> <dependency> <groupId>com.example</groupId> <artifactId>missing-lib</artifactId> <version>1.0</version> <scope>compile</scope> <!-- 确保不是test/runtime --> </dependency> ``` 执行 `mvn dependency:tree` 检查依赖传递 - **Gradle 项目**: ```gradle // 检查依赖配置 dependencies { implementation 'com.example:missing-lib:1.0' // 正确作用域 // runtimeOnly 或 compileOnly 可能导致问题 } ``` 运行 `./gradlew dependencies --configuration runtimeClasspath` #### **步骤 2:检查类文件存在性** - 解压 JAR/WAR 文件确认 `.class` 存在: ```bash jar tf your-app.jar | grep "TdrCtrl.class" unzip -l android-app.apk | grep "SrWindowManagerService" ``` - 确保包路径匹配(如 `com/example/MyClass.class` 对应 `com.example.MyClass`)[^4] #### **步骤 3:处理静态初始化失败** - 检查错误日志中是否有 `Caused by: ExceptionInInitializerError` - 在静态块中添加异常捕获: ```java static { try { // 初始化代码 } catch (Exception e) { throw new RuntimeException("静态初始化失败", e); } } ``` #### **步骤 4:Android 特殊处理** 1. **系统类访问问题**: ```java // 避免反射内部类,改用公开API WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); ``` 2. **ProGuard 保留规则**: ```proguard -keep class com.android.server.wm.SrWindowManagerService { *; } -dontwarn com.android.server.wm.** ``` 3. **Multidex 配置**(Android 5.0 前): ```gradle android { defaultConfig { multiDexEnabled true } } dependencies { implementation 'androidx.multidex:multidex:2.0.1' } ``` #### **步骤 5:类加载调试** 添加诊断代码检查类加载: ```java public static boolean isClassLoaded(String className) { try { Class.forName(className); return true; } catch (ClassNotFoundException e) { return false; } } // 调用示例 if (!isClassLoaded("com.android.server.wm.SrWindowManagerService")) { Log.e("TAG", "类加载失败,检查依赖"); } ``` --- ### **预防措施** 1. **构建工具检查**: - Maven:`mvn clean compile test` - Gradle:`./gradlew clean build` 2. **依赖分析工具**: - JDeps:`jdeps -verbose:class your-app.jar` - Android Lint:检查非法 API 调用 3. **单元测试覆盖**: ```java @Test public void testClassAvailability() { assertNotNull(ClassLoader.getSystemResource("com/example/CriticalClass.class")); } ``` > **关键提示**:当错误涉及 `SrWindowManagerService` 等系统类时,90% 以上是非法访问系统内部 API 导致。Google Play 严格禁止此行为[^1],需改用公开 API。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值