Search code examples
androidopencvgradledl4j

ND4J Shared library can not be find in Android project


I'm working on this Android project that need both OpenCV and DL4J. But there is this conflict btw the two during dynamic linking.

In my app/src/main/jniLibs: I have to include arm64-v8a folder which has file libopencv_java3.so. However, now this causes the linker to try finding libdl.so and/or libjnind4jcpu.so in this arm64-v8a folder, which obviously won't be there since DL4J is added from remote repository.

So, is there a way to explicitly tell Gradle to find libdl.so and/or libjnind4jcpu.so from the remote repository? Or what would be your way to find to solve this issue?


build.gradle

apply plugin: 'com.android.application'

android {
     compileSdkVersion 25
     buildToolsVersion '26.0.2'

defaultConfig {
    applicationId "gov.nih.nlm.malaria_screener"
    minSdkVersion 19
    targetSdkVersion 25
    versionCode 6 // start from 1
    versionName "1.3.2" // start from 1.0
    multiDexEnabled true
    jackOptions { // for Java 1.8
        enabled true
    }
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 
'proguard-rules.pro'
    }
}

lintOptions { // for unsigned release build error on Time and Date picker
    checkReleaseBuilds false
}
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}



}

dependencies {
    compile files('libs/GraphView-4.0.1.jar')
    compile files('libs/AndroidSwipeLayout-v1.1.8.jar')
    compile 'com.dropbox.core:dropbox-core-sdk:2.0.1'
    compile files('libs/dropbox-android-sdk-1.6.3.jar')
    compile files('libs/json_simple-1.1.jar')
    compile files('libs/eventbus-3.0.0.jar')
    compile files('libs/glide-3.7.0.jar')
    compile files('libs/flickrj-android-2.0.0.jar')
    compile 'org.deeplearning4j:deeplearning4j-core:0.7.2'
    compile 'org.nd4j:nd4j-native:0.7.2'
    compile 'org.nd4j:nd4j-native:0.7.2:android-x86'
    compile 'org.nd4j:nd4j-native:0.7.2:android-arm'
//    implementation 'org.deeplearning4j:deeplearning4j-core:0.9.1'
//    implementation 'org.nd4j:nd4j-native:0.9.1'
//    implementation 'org.nd4j:nd4j-native:0.9.1:android-x86'
//    implementation 'org.nd4j:nd4j-native:0.9.1:android-arm'
//    implementation 'org.bytedeco.javacpp-presets:openblas:0.2.19-1.3:android-x86'
//    implementation 'org.bytedeco.javacpp-presets:openblas:0.2.19-1.3:android-arm'
    annotationProcessor 'org.projectlombok:lombok:1.16.10'
    compile project(':mysql-connector-java-5.1.43-bin')
    compile 'com.android.support:appcompat-v7:25.4.0'
    compile 'com.android.support:design:25.4.0'
    compile 'com.android.support:cardview-v7:25.4.0'
    compile 'com.android.support:support-v13:25.4.0'
    compile 'com.android.support:support-v4:25.4.0'
    compile 'com.android.support:recyclerview-v7:25.4.0'
    compile 'com.github.amlcurran.showcaseview:library:5.4.3'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation project(':openCVLibrary340')

Error:

 E/linker: library "/system/lib64/libdl.so" ("/system/lib64/libdl.so") needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths="", default_library_paths="/data/app/gov.nih.nlm.malaria_screener-1/lib/arm64:/data/app/gov.nih.nlm.malaria_screener-1/base.apk!/lib/arm64-v8a", permitted_paths="/data:/mnt/expand:/data/data/gov.nih.nlm.malaria_screener"]
02-01 15:41:09.975 20294-22826/gov.nih.nlm.malaria_screener E/AndroidRuntime: FATAL EXCEPTION: Thread-5
                                                                              Process: gov.nih.nlm.malaria_screener, PID: 20294
                                                                              java.lang.ExceptionInInitializerError
                                                                                  at org.nd4j.nativeblas.NativeOpsHolder.getInstance(NativeOpsHolder.java:45)
                                                                                  at org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:41)
                                                                                  at java.lang.Class.newInstance(Native Method)
                                                                                  at org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5646)
                                                                                  at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5554)
                                                                                  at org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:189)
                                                                                  at org.nd4j.linalg.factory.Nd4j.read(Nd4j.java:2328)
                                                                                  at org.deeplearning4j.util.ModelSerializer.restoreMultiLayerNetwork(ModelSerializer.java:216)
                                                                                  at org.deeplearning4j.util.ModelSerializer.restoreMultiLayerNetwork(ModelSerializer.java:167)
                                                                                  at gov.nih.nlm.malaria_screener.Cells.<init>(Cells.java:117)
                                                                                  at gov.nih.nlm.malaria_screener.CameraActivity.ProcessImage(CameraActivity.java:1104)
                                                                                  at gov.nih.nlm.malaria_screener.CameraActivity$8.run(CameraActivity.java:874)
                                                                                  at java.lang.Thread.run(Thread.java:762)
                                                                               Caused by: java.lang.RuntimeException: ND4J is probably missing dependencies. For more information, please refer to: http://nd4j.org/getstarted.html
                                                                                  at org.nd4j.nativeblas.NativeOpsHolder.<init>(NativeOpsHolder.java:40)
                                                                                  at org.nd4j.nativeblas.NativeOpsHolder.<clinit>(NativeOpsHolder.java:16)
                                                                                  at org.nd4j.nativeblas.NativeOpsHolder.getInstance(NativeOpsHolder.java:45) 
                                                                                  at org.nd4j.linalg.cpu.nativecpu.ops.NativeOpExecutioner.<init>(NativeOpExecutioner.java:41) 
                                                                                  at java.lang.Class.newInstance(Native Method) 
                                                                                  at org.nd4j.linalg.factory.Nd4j.initWithBackend(Nd4j.java:5646) 
                                                                                  at org.nd4j.linalg.factory.Nd4j.initContext(Nd4j.java:5554) 
                                                                                  at org.nd4j.linalg.factory.Nd4j.<clinit>(Nd4j.java:189) 
                                                                                  at org.nd4j.linalg.factory.Nd4j.read(Nd4j.java:2328) 
                                                                                  at org.deeplearning4j.util.ModelSerializer.restoreMultiLayerNetwork(ModelSerializer.java:216) 
                                                                                  at org.deeplearning4j.util.ModelSerializer.restoreMultiLayerNetwork(ModelSerializer.java:167) 
                                                                                  at gov.nih.nlm.malaria_screener.Cells.<init>(Cells.java:117) 
                                                                                  at gov.nih.nlm.malaria_screener.CameraActivity.ProcessImage(CameraActivity.java:1104) 
                                                                                  at gov.nih.nlm.malaria_screener.CameraActivity$8.run(CameraActivity.java:874) 
                                                                                  at java.lang.Thread.run(Thread.java:762) 
                                                                               Caused by: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/gov.nih.nlm.malaria_screener-1/base.apk"],nativeLibraryDirectories=[/data/app/gov.nih.nlm.malaria_screener-1/lib/arm64, /data/app/gov.nih.nlm.malaria_screener-1/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]] couldn't find "libjnind4jcpu.so"
                                                                                  at java.lang.Runtime.loadLibrary0(Runtime.java:972)

Solution

  • Since you only include android-x86 and android-arm using those lines

    compile 'org.nd4j:nd4j-native:0.7.2:android-x86'
    compile 'org.nd4j:nd4j-native:0.7.2:android-arm'
    

    you will be missing arm64 libs in your apk. If you unzip it and look into libs folder you will see smth like

     libs   
    |-->x86   
    |    |-->libopencv_java3.so   
    |    |-->libdl.so   
    |-->armeabi   
    |    |-->libopencv_java3.so   
    |    |-->libdl.so   
    |-->arm64   
         |-->libopencv_java3.so   
    

    So when you launch your app it would try to look for libdl in arm64 which doesn't have one.

    Possible solutions:

    1. Add arm64 version of nd4j lib. Also note that this is preferred because Google remove 32 bit support in 2019

    2. Exclude arm64 from your build using this method