Android NDK : No JNI_OnLoad found in ... skipping init : But there is JNI_OnLoad

11,341

By help of @AlexCohn, I found out my error. And what a silly stupid error it was.

jni/Android.mk

  include $(CLEAR_VARS)
  LOCAL_MODULE := me
- LOCAL_SRC_FILE := me.c
+ LOCAL_SRC_FILES := me.c
  include $(BUILD_SHARED_LIBRARY)

Because of this, me.c wasn't compiling. Hence it was not included in the built shared library. I had wasted a couple of hours on this at least.

Share:
11,341
venky
Author by

venky

A Curious human being and Open source enthusiast ...

Updated on June 04, 2022

Comments

  • venky
    venky almost 2 years

    I am asking this question again because I have to.

    I am having this error while running a NDK based application.

    D dalvikvm: No JNI_OnLoad found in /data/app-lib/com.venky-1/libme.so 0xa5082228, skipping init W dalvikvm: No implementation found for native Lcom/venky/Home;.getPermission:(Landroid/app/Activity;)I

    I have been through

    1. No JNI_OnLoad found in ... skipping init
    2. No JNI_OnLoad found skipping init > Application shutdown
    3. No JNI_Onload() found and VM shutting down
    4. JNI_OnLoad not found

    Their problem was either

    1. They were not using JNI_OnLoad because they used JNI specific naming convention (For example Java_com_venky_Home_start()). Hence this message has no significance as there is an alternative.
    2. They were using C++ and there was function name mangling.

    My case is entirely different. And the above two are invalid in my case. I am using C files. So no mangling. And I am not using JNI kind of function names. I am manually registering the functions using JNI_OnLoad. Hence my conclusion is that "No Implementation Found" is due to the fact that the application is somehow unable to find JNI_OnLoad. But why? It is present in the C file.

    Relevant sections of code are as follows. Please ask if you need more.

    jni/Android.mk

    include $(CLEAR_VARS)
    LOCAL_MODULE := me
    LOCAL_SRC_FILE := me.c
    include $(BUILD_SHARED_LIBRARY)
    

    com/venky/Home.java

    package com.venky;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class Home extends Activity {
    
        static {
            System.loadLibrary("me");
        }
    
    
        private native int getPermission(Activity activity);
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.home);
            getPermission(this);
        }
    }
    

    jni/me.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <string.h>
    #include <android/log.h>
    #include <jni.h>
    
    #define LOG_TAG "com.venky.me"
    
    #define LOG_D(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    #define LOG_F(fn_name) __android_log_write(ANDROID_LOG_DEBUG, LOG_TAG, "Called : " fn_name )
    
    static JavaVM *java_vm;
    
    jint JNI_OnLoad(JavaVM *vm, void *reserved)
    {
        LOG_F ("JNI_OnLoad");
        java_vm = vm;
    
        // Get JNI Env for all function calls
        JNIEnv* env;
        if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
            LOG_D ("GetEnv failed.");
            return -1;
        }
    
        // Find the class calling native function
        jclass NativeUsb = (*env)->FindClass(env, "com/venky/Home");
        if (class_home == NULL) {
            LOG_D ("FindClass failed : No class found.");
            return -1;
        }
    
        // Register native method for getUsbPermission
        JNINativeMethod nm[1] = {
            { "getPermission", "(Landroid/app/Activity;)I", get_permission}
        };
    
        if ((*env)->RegisterNatives(env, NativeUsb, nm , 1)) {
             LOG_D ("RegisterNatives Failed.");
             return -1;
        }
    
        return JNI_VERSION_1_6;
    }
    
    int get_permission (jobject activity)
    {
        LOG_F ("get_usb_permission");
    
    }