【问题标题】:My native method isn't being found by the Java endJava端没有找到我的本机方法
【发布时间】:2014-10-17 15:32:52
【问题描述】:

Java 端没有找到我的本地方法

我的Activity 子类有:

package com.dumb_dumber.myproject;

public class SubActivity extends SDLActivity {//which extends Activity

    private static native void nativeInitGPGS(SubActivity act);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        instance = this;
        nativeInitGPGS(this);
    }

main.cpp 开始时,在第一个预处理指令之后:

extern "C"
{
JNIEXPORT void
Java_com_dumb_1dumber_myproject_SubActivity_nativeInitGPGS(JNIEnv* env, jobject thiz, jobject activity)
{

我知道我已经插入了一个 1 以使其成为 dumb_1dumber,这就是 Javah 告诉我要做的,并且在过去使用不同的框架进行了工作。我试过删除 1 无效。

我还是明白了:

10-17 16:12:38.051: D/dalvikvm(4980): 试图加载 lib /data/data/com.dumb_dumber.myproject/lib/libmain.so 0x423849c8
10-17 16:12:38.055:D/dalvikvm(4980):添加了共享库 /data/data/com.dumb_dumber.myproject/lib/libmain.so 0x423849c8
10-17 16:12:38.060: V/SDL(4980): onCreate():null
10-17 16:12:38.087: W/dalvikvm(4980): 找不到本地 Lcom/dumb_dumber/myproject/SubActivity 的实现;.nativeInitGPGS:(Lcom/dumb_dumber/myproject/SubActivity;)V
10-17 16:12:38.108: D/AndroidRuntime(4980): 关闭 VM
10-17 16:12:38.108: W/dalvikvm(4980): threadid=1: 线程以未捕获的异常退出 (group=0x41b73908)
10-17 16:00:52.456: E/AndroidRuntime(4699): 致命异常: main
10-17 16:00:52.456: E/AndroidRuntime(4699): java.lang.UnsatisfiedLinkError: 找不到本机方法: com.dumb_dumber.myproject.SubActivity.nativeInitGPGS:(Lcom/dumb_dumber/myproject/SubActivity;)V
10-17 16:00:52.456: E/AndroidRuntime(4699): at com.dumb_dumber.myproject.SubActivity.nativeInitGPGS(Native Method)
10-17 16:00:52.456: E/AndroidRuntime(4699): at com.dumb_dumber.myproject.SubActivity.onCreate(SubActivity)

我相信本机实现可以放置在任何地方并自动获取。我尝试将 C 实现放在另一个 cpp 主体中,而不是 main.cpp,但没有任何变化。

这是我的Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := main

SDL_PATH := ../SDL

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include

LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
                    main.cpp
#Other stuff removed for clarity

LOCAL_SHARED_LIBRARIES :=   SDL2_image \
                            SDL2    \
                            SDL2_ttf
LOCAL_WHOLE_STATIC_LIBRARIES += gpg_static

LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog -lz

include $(BUILD_SHARED_LIBRARY)

虽然我将共享库的加载留给SDLActivity

static {
    System.loadLibrary("SDL2");
    System.loadLibrary("SDL2_image");
    System.loadLibrary("SDL2_ttf");
    System.loadLibrary("main");
}

我花了很长时间才来到这里,我已经构建了很多不错的 cpp 以期待一个令人满意的解决方案,但我意识到这可能是不可能的,至少我不可能。我在 jni 目录中有 remembered to run ndk-build(两次),并试图在我的手机上运行。

我已经通过 hexeditor 运行了我的 libmain.so,并且可以确认它存在,并且 _1 就位。我可以尝试的不多,但是有时间尝试一下意味着我可以尝试删除下划线。现在又试了,没区别。

这是nm 的前六行输出,感谢 Alex,

    U IMG_Init  
    U IMG_Load  
    U IMG_Quit  

00065454 T JNI_OnLoad
0005c208 T Java_org_libsdl_app_SDLActivity_nativeInit
0006851c T Java_com_dumbdumber_myproject_SubActivity_nativeInitGPGS

                            ^^^^^^^^^ 

更新是的,再次感谢 Chris,myproject 在您标记我的原始活动类型名称/jobject 参数后被省略。

【问题讨论】:

  • Android NDK 附带一个实用程序nm,它采用参数-D。然后你可以看到你的.so 的导出函数列表,并且检查它们的名字没有像你想象的那样被破坏。
  • 谢谢@AlexCohn 就如预期的那样,我会更新操作
  • 您已经用一个无关的“1”显示它,并且没有下划线,但不仅仅是下划线与包名称匹配。或者在 either 本机 或 Java 端没有下划线。
  • @ChrisStratton 正如我所说,我已经尝试了一切,最后一次更新,从上到下的顺序阅读表明我已经放弃在我的包名称中使用下划线。抱歉,这不是很清楚,尽量不要写一个库。我还发现“无关 1”是必不可少的,它具有不同的框架,我的意思是代替 SDL,而不是 Java 或其他东西。这实际上是我能想到的一切。我将不可避免地回到纯 Java。 :(
  • 如果您从 NDK 示例构建 hello-jni 项目,您将看到,如果您不对其提出极端要求,则此链接有效。你说你已经放弃了命名中的下划线,但显然还没有基于安装测试的完全干净的重建。您似乎还混合了包含和不包含“myproject”的包名称 - 例如,您的 nm 输出中缺少该部分。

标签: java android c++ android-ndk java-native-interface


【解决方案1】:
Java_com_dumb_1dumber_myproject_SubActivity_nativeInitGPGS

不匹配

package com.dumb_dumber.myproject;

public class SubActivity extends SDLActivity {//which extends Activity

   private static native void nativeInitGPGS(AnagrActivity act);

因此没有找到实现错误。

从您的本机方法名称中删除多余的“1”。还可以考虑选择一个更合理的包名称其中不带下划线

我已经通过 hexeditor 运行了我的 libmain.so,并且可以确认它存在,并且 _1 就位

确实如此。虽然您的错误跟踪清楚地表明链接器正在寻找一个没有那个无关字符的函数。也许这是 Java 与 Dalvik 或 ART 之间实现差异的一个怪癖 - 无论如何,您只是因为不必要的新颖包名称而体验它。

【讨论】:

  • 我觉得完全有必要看到它是我最近购买的域名。我已经更新了问题以显示完全删除下划线的效果。正如我最初所说,我已经尝试过两种命名约定,有和没有 extraneous 1
  • 您的 java 包名称不需要与您的域名匹配(无论如何,您很有可能在商标诉讼中败诉)。您的本机代码及其所属的类也不需要与您的 java 代码的其他部分属于相同的包名。
  • 我认为这个想法是每个域名所有者都会获得一个唯一的包名。显然很难执行,但我正在努力遵守这个简单的理想。
  • 同样,您的内部功能的包名称不必与您的 apk 本身的名称匹配。只有后者需要是唯一的 - 你可以有一个组件,如 com.globallyunique.name/com.overused.example.MyActivity 和 JNI 只会看到类的包名,而不是包含 apk 的唯一命名的包.
  • 谢谢你的重复,我相信你的钱是对的,我只是粗心,你是说我清单中的包名可以代表我域名中的下划线,而我的java包可以独立命名吗?
猜你喜欢
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
  • 2012-08-15
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多