java.lang.NoSuchFieldError: No static field INSTANCE of type org/apache/http/conn/ssl/AllowAllHostna
迁移 Java Sample 到 Android 项目中,使用 `org.apache.http` 库运行时报错
一、报错描述
迁移 Java Sample 到 Android 项目中,使用 org.apache.http 库运行时报错如下:
FATAL EXCEPTION: pool-2-thread-1 (Ask Gemini)
Process: com.xxx.devicemanager, PID: 18821
java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; in class Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; or its superclasses (declaration of 'org.apache.http.conn.ssl.AllowAllHostnameVerifier' appears in /system/framework/framework.jar!classes5.dex)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>(SSLConnectionSocketFactory.java:151)
at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:981)
at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:56)
at com.xxx.devicemanager.utils.HttpClientUtils.doPostJson(HttpClientUtils.java:200)
at com.xxx.devicemanager.CloudLinkManager$1.lambda$onSuccess$0$com-xxx-devicemanager-CloudLinkManager$1(CloudLinkManager.java:195)
at com.xxx.devicemanager.CloudLinkManager$1$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
使用 org.apache.httpcomponents:httpclient 4.5.14,当Android Studio 编译时候也会报错,添加如下编译通过
android {
...
packaging {
exclude 'META-INF/DEPENDENCIES'
}
...
}
二、报错分析
这个问题是一个典型的在 Android 开发中遇到的库冲突问题。错误日志 java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/conn/ssl/AllowAllHostnameVerifier; 表明,您的代码在运行时加载的 AllowAllHostnameVerifier 类版本中,并不存在一个名为 INSTANCE 的静态字段。
这个问题的根本原因在于 库版本冲突。具体来说:
- Android 系统自带了 Apache HttpClient 库:为了历史兼容性,Android 系统本身在
framework.jar中内置了一个版本的 Apache HttpClient 库。然而,这个系统内置的版本通常比较旧。 - 您的应用或其依赖的库引入了新版本的 HttpClient:您的应用(
com.xxx.devicemanager)或者它所依赖的某个库(例如某个网络请求库)也引入了一个较新版本的 Apache HttpClient。 - 冲突发生:在运行时,Java 虚拟机(JVM)加载了 Android 系统提供的旧版本
AllowAllHostnameVerifier类。从错误信息中的路径/system/framework/framework.jar!classes5.dex可以确认这一点。然而,您的代码(具体是在org.apache.http.conn.ssl.SSLConnectionSocketFactory.<clinit>)是基于新版 HttpClient 编译的,它期望AllowAllHostnameVerifier类中有一个INSTANCE静态字段。由于加载的是没有这个字段的旧版本类,因此抛出了NoSuchFieldError异常。
这个问题在 Android 6.0 (API 23) 及以上版本尤为常见,因为从这个版本开始,Google 不再推荐使用 Apache HTTP 客户端,并对其支持做了变更。
三、解决方案
使用专门为 Android 优化的 HttpClient 库(推荐)
最直接且推荐的解决方法是,使用一个已经处理了这类冲突的第三方库,这个库会将 Apache HttpClient 的类重新打包到一个新的命名空间下,从而避免和系统自带的库冲突。
1.在您项目的 build.gradle (Module: app) 文件中,添加以下依赖:
dependencies {
// ... 其他依赖
implementation 'cz.msebera.android:httpclient:4.5.8' // 或者更新的版本
}
2.修改您的代码,将所有 org.apache.http 的 import 语句修改为 cz.msebera.android.httpclient。例如:
import org.apache.http.HttpResponse;->import cz.msebera.android.httpclient.HttpResponse;import org.apache.http.client.HttpClient;->import cz.msebera.android.httpclient.client.HttpClient;
这种方法的优点是能够彻底解决命名空间冲突的问题。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)