java.lang.NoSuchFieldError: no "I" field XXXXin class "Lxx/xx/xx/xx;" or its superclasses

本文详细介绍了使用C语言通过JNI调用Java方法的过程,并针对一个常见错误——NoSuchFieldError进行了深入分析。文章展示了如何创建Java对象、设置字段值及解决特定编译器警告的重要性。

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

用C语言写jni调用的时候,先FindClass ,之后通过GetFieldID 获取变量 然后通过SetIntField 等 去赋值


大约的流程如下:

// 获取类

clsDay = (*env)->FindClass(env, "com/xxx/xxx/xxxx/Day");

//获取method ,一般都是固定写法

jmethodID mid_init = (*env)->GetMethodID(env, clsDay , "<init>", "()V");

//创建对象

jobject data_struct = (*env)->NewObject(env, clsDay , mid_init);

//获取类里的变量
jfieldID type = (*env)->GetFieldID(env, clsDay , "type", "I");
jfieldID mon= (*env)->GetFieldID(env, clsDay , "mon", "F");


//给变量赋值
(*env)->SetIntField(env, data_struct, type, 1);
(*env)->SetFloatField(env, data_struct, mon, 12.00f);


如果类Day里面有 

{

int type;

float mon;

}

但老是找不到type

java.lang.NoSuchFieldError: no "I" field type in class "Lxx/xx/xx/xx;" or its superclasses 


关于这个报错,排查了很多次, 发现,如果你在Day这个类里面,没有去使用type, 就会报这个错误。所以在写代码时,一些编辑器给的警告也要注意下。

<think>我们正在处理一个Java异常问题:java.lang.NoSuchFieldError,具体是"No static field"。这个错误通常发生在运行时,当程序试图访问一个类的静态字段,但该字段在编译时存在而在运行时不存在时抛出。 根据经验,这个错误可能的原因和解决方案如下: ### 原因分析 1. **版本不一致**:最常见的原因是编译时使用的库版本和运行时使用的库版本不一致。例如,在编译时引用的类库中包含某个静态字段,但在运行时的类库中该字段已被移除或重命名。 2. **多个库冲突**:项目依赖了多个库,这些库包含了相同类名的不同实现,导致运行时加载了不包含该静态字段的类。 3. **ProGuard/R8混淆问题**:如果使用了代码混淆工具,可能因为混淆规则导致某些字段被移除或重命名,从而引发该错误。 4. **动态生成类**:某些框架(如反射、字节码操作)动态生成的类与预期不符,缺少了应有的静态字段。 ### 解决方案 1. **检查依赖版本**:确保编译和运行时使用的所有库版本一致。特别是检查引发错误的类所在的库版本。可以使用Maven或Gradle的依赖树命令(如`mvn dependency:tree`或`gradle dependencies`)来检查依赖冲突。 2. **解决依赖冲突**:如果存在多个版本的库,需要排除重复的或冲突的版本。在构建工具中可以通过`exclude`语句排除冲突的依赖。 3. **检查混淆规则**:如果使用了混淆工具,检查混淆规则是否保留了该字段。可以通过添加规则来保留特定的字段,例如: ```proguard -keepclassmembers class com.example.MyClass { public static <fields>; } ``` 4. **清理和重新构建**:执行清理操作(如删除`target`或`build`目录)并重新构建项目,确保没有残留的旧编译文件。 5. **检查类加载器**:在复杂应用(如OSGi、Servlet容器)中,可能存在类加载器隔离问题。确保包含该类的库被正确的类加载器加载。 ### 示例代码 假设错误信息如下: ``` java.lang.NoSuchFieldError: No static field myField of type I in class Lcom/example/MyClass; ``` 这表示在类`com.example.MyClass`中找不到名为`myField`的静态整型字段。你需要检查运行时类路径下的`com/example/MyClass.class`文件,确认该字段是否存在。可以使用反编译工具或`javap`命令查看类的结构: ```bash javap -classpath your_classpath com.example.MyClass ``` 如果该字段确实存在,那么可能是类加载问题;如果不存在,则需要更新依赖库或调整构建配置。 通过以上步骤,通常可以解决`NoSuchFieldError`问题。 §§相关问题§§ 1. 如何查看Java项目的依赖树? 2. 在Maven中如何排除传递依赖? 3. 如何配置ProGuard规则以避免混淆特定的字段或类? 4.Android开发中遇到`NoSuchFieldError`有哪些常见原因?</think>### `java.lang.NoSuchFieldError: No static field` 的原因与解决方案 #### **错误原因** 1. **编译/运行时类版本不一致** - 最常见原因:编译时使用的类库版本包含该静态字段,但运行时加载的类库版本中该字段已被移除或重命名。 - 示例: - 编译时:`v1.0` 的 `Utils.class` 包含 `public static int FLAG;` - 运行时:`v2.0` 的 `Utils.class` 删除了 `FLAG` 字段 → 抛出 `NoSuchFieldError`[^1]。 2. **依赖冲突** - 项目依赖了多个库的相同类(如 `com.example.Foo`),但不同库的版本字段不一致。 - 类加载器意外加载了不包含该字段的类版本。 3. **混淆/优化问题** - ProGuard/R8 等工具错误移除了字段(未正确配置保留规则)。 4. **反射修改失败** - 尝试通过反射修改 `final static` 字段时,未正确处理字段修饰符或访问权限(参考引用内容)[^1]。 --- #### **解决方案** 1. **检查依赖一致性** - **Maven**:运行 `mvn dependency:tree` 检查依赖树,排除冲突版本: ```xml <dependency> <groupId>com.example</groupId> <artifactId>problem-lib</artifactId> <version>1.0</version> <exclusions> <exclusion> <groupId>conflict-group</groupId> <artifactId>conflict-artifact</artifactId> </exclusion> </exclusions> </dependency> ``` - **Gradle**:使用 `./gradlew dependencies` 查看依赖,强制指定版本: ```groovy configurations.all { resolutionStrategy.force 'com.example:lib:1.0' } ``` 2. **验证类文件字段是否存在** - 使用 `javap` 检查运行时类是否包含该字段: ```bash javap -classpath your_app.jar com.example.Utils | grep FLAG ``` - 若输出为空 → 字段在运行时不存在。 3. **配置混淆规则** 在 ProGuard/R8 配置中保留字段: ```proguard -keepclassmembers class com.example.Utils { public static *** FLAG; } ``` 4. **正确通过反射修改 `final static` 字段** ```java Field field = Utils.class.getDeclaredField("FLAG"); field.setAccessible(true); // 移除 final 修饰符 Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, 123); // 设置新值 ``` > ⚠️ 警告:此操作破坏不可变性,需谨慎使用。 5. **清理构建缓存** 删除 `/target`(Maven)或 `/build`(Gradle)目录后重新构建。 --- #### **预防措施** - 使用依赖管理工具(如 Maven BOM)统一库版本。 - 在 CI/CD 流程中添加依赖一致性检查(如 `mvn versions:display-dependency-updates`)。 - 避免直接反射修改 `final` 字段,改用设计模式(如依赖注入)。 --- ### 相关问题 1. 如何检测 Java 项目中的依赖冲突? 2. ProGuard 和 R8 在字段保留规则配置上有何区别? 3. 反射修改 `final static` 字段时,为什么需要调整 `modifiers` 属性? 4. 除了 `NoSuchFieldError`,还有哪些常见的运行时类版本不匹配导致的错误? [^1]: 引用来源:通过反射修改 `final static` 字段需调整字段修饰符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值