0

0

JNI调用失败:NoSuchMethodError的根源与修复方案

花韻仙語

花韻仙語

发布时间:2026-02-15 17:24:02

|

735人浏览过

|

来源于php中文网

原创

JNI调用失败:NoSuchMethodError的根源与修复方案

本文详解jni环境下因java类继承关系缺失导致nosuchmethoderror的典型问题,重点说明为何自定义类调用android系统方法(如getpackagemanager)失败,并提供正确继承activity、合理管理native库加载及方法声明的完整解决方案。

本文详解jni环境下因java类继承关系缺失导致nosuchmethoderror的典型问题,重点说明为何自定义类调用android系统方法(如getpackagemanager)失败,并提供正确继承activity、合理管理native库加载及方法声明的完整解决方案。

在Android JNI开发中,NoSuchMethodError看似指向Native层,实则常源于Java端的类设计缺陷。您遇到的错误:

JNI DETECTED ERROR IN APPLICATION: 
JNI CallObjectMethodV called with pending exception java.lang.NoSuchMethodError: 
no non-static method "Lru/integrics/mobileschool/view/activity/MainActivity;.getPackageManager()Landroid/content/pm/PackageManager;"

明确指出:JVM在JNI调用过程中试图通过CallObjectMethodV反射调用MainActivity.getPackageManager(),但该方法在当前类中根本不存在——因为MainActivity未继承android.app.Activity(或其子类,如AppCompatActivity),而getPackageManager()是Activity基类提供的标准API。

❌ 错误根源分析

您的代码中:

public class MainActivity {
    public MainActivity(){
        System.loadLibrary("x2");
    }
    public native String x01(String str);
    public String get(String str){
        String key = Base64.encodeToString(x01(str.substring(0, str.length() / 2)).getBytes(), Base64.NO_WRAP);
        return key;
    }
}
  • MainActivity 是一个普通Java类,不继承任何Android组件;
  • 但Native .so 库(libx2.so)内部可能隐式调用了getPackageManager()(例如通过env->CallObjectMethod(obj, methodID, ...)),期望obj是有效的Activity实例;
  • JVM发现目标对象无此方法,抛出NoSuchMethodError并终止JNI调用。

⚠️ 注意:将Java方法声明为static无法解决此问题——getPackageManager()是实例方法,且必须由Activity实例提供上下文环境(如Context、Application等)。单纯加static反而会破坏JNI调用契约。

绘蛙AI视频
绘蛙AI视频

绘蛙推出的AI模特视频生成工具

下载

✅ 正确实现方式

1. 继承 Activity(或 AppCompatActivity)

确保 MainActivity 是真正的Activity组件:

package ru.integrics.mobileschool.view.activity;

import android.app.Activity;
import android.util.Base64;
import android.os.Bundle;

public class MainActivity extends Activity { // ✅ 关键:继承Activity

    static {
        System.loadLibrary("x2"); // ✅ 推荐:在static块中加载,确保类初始化时完成
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 可在此调用Native方法
        String result = get("test");
        // ...
    }

    public native String x01(String str);

    public String get(String str) {
        if (str == null || str.length() == 0) return "";
        String half = str.substring(0, str.length() / 2);
        String nativeResult = x01(half);
        if (nativeResult == null) nativeResult = "";
        return Base64.encodeToString(nativeResult.getBytes(), Base64.NO_WRAP);
    }
}

2. 验证Native侧调用逻辑(C/C++端提示)

若您控制.so源码,请检查是否误调用了Android框架方法。例如以下C代码是危险的

// ❌ 错误:假设jobject是Activity,但未校验
jmethodID getPM = (*env)->GetMethodID(env, clazz, "getPackageManager", 
                                       "()Landroid/content/pm/PackageManager;");
(*env)->CallObjectMethod(env, obj, getPM); // 若obj非Activity实例,崩溃!

✅ 安全做法应先判断类型或仅在明确持有Activity引用时调用:

// ✅ 示例:仅当传入的是Activity子类实例时才调用
jclass activityClass = (*env)->FindClass(env, "android/app/Activity");
jboolean isActivity = (*env)->IsInstanceOf(env, obj, activityClass);
if (isActivity) {
    jmethodID getPM = (*env)->GetMethodID(env, activityClass, "getPackageManager", 
                                           "()Landroid/content/pm/PackageManager;");
    jobject pm = (*env)->CallObjectMethod(env, obj, getPM);
    // ...
}

? 关键注意事项总结

  • 继承不可省略:所有需访问Android系统服务(getPackageManager()、getResources()、startActivity()等)的Java类,必须直接或间接继承Context子类(如Activity、Service、Application)。
  • System.loadLibrary()位置建议:放在static块中,避免多次加载;切勿在构造函数中调用(此时类尚未完全初始化,且Activity构造函数不应被显式调用)。
  • Native方法签名一致性:确保.so中JNIEXPORT函数名与Java声明严格匹配(含包路径,如Java_ru_integrics_mobileschool_view_activity_MainActivity_x01)。
  • 空值防护:Native返回字符串可能为NULL,Java端需判空,避免NullPointerException。

遵循以上规范,即可彻底规避此类NoSuchMethodError,构建健壮的JNI交互逻辑。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

244

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

726

2024.03.01

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

244

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

726

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

551

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

214

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1552

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

640

2023.11.24

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

145

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号