Trouble Installing on Android Device Running Arm Processor

I’ll give it a shot.

I am curious though, if everything was building fine (which I assume means that everything was compiling fine as well), why wasn’t the missing library(s) caught then at build/compile time?

By using the javacpp.platform option, you tell the build system what it should include. So from the point of view of the build everything was included just fine.

Now, at runtime, it is trying to load what it has included, and it looks like it can not load those included libraries. This may have many reasons. One of them may be that you’ve selected the wrong platform, another one maybe that all of the platforms that we have don’t work with termux.

I’ve taken a look at Differences from Linux - Termux Wiki and it says

To have best compatibility with Android OS and remove the need of maintaining custom toolchains we compile all our packages with Android NDK. Resulting binaries are linked against Bionic libc (files libc.so, libm.so, libdl.so from /system/lib or /system/lib64).

So I expect that the Linux platform libraries are unlikely to work, as they expect there to be a glibc. The android platform libraries may work, but I don’t have high hopes that they actually do.

I looked inside the uber jar file and it has a lot of things inside it. It is a massive file so I’m not sure if I will be able to post all of its contents here. I uploaded it to my Github if you wanted to take a look at it (URL: https://github.com/Procambarus-gracilis/Auto_NRG_Mapper/blob/master/contents.txt) but I think it’s so big that Github only allows downloads of it and will not allow a view of its contents.

Alternatively, could you tell me what are the files I should be looking for in this output that are of interest to the errors I am getting?

Here are the 4 errors I was getting:

  1. Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
    Exception in thread “main” java.lang.ExceptionInInitializerError

  2. Caused by: java.lang.RuntimeException: ND4J is probably missing dependencies. For more information, please refer to: https://deeplearning4j.konduit.ai/nd4j/backend

  3. Caused by: java.lang.UnsatisfiedLinkError: no jniopenblas_nolapack in java.library.path

  4. Caused by: java.lang.UnsatisfiedLinkError: no openblas in java.library.path

Thanks.

Well, for example, org/bytedeco/javacpp/linux-armhf/libjnijavacpp.so is there, but that’s not going to work with Android…

After listing the jar’s contained files, I looked for the directory you suggested and although I was unable to find the file you mentioned called “libjnijavacpp.so” in that specific directory, I did find the file in the following directory instead: lib/armeabi-v7a/libjnijavacpp.so (armeabi-v7a is my processor type). Similarly, I found lib/armeabi-v7a/libjniopenblas_nolapack.so (I assume this is the file that addresses the “no jniopenblas_nolapack in java.library.path” error). I also found found lib/armeabi-v7a/libopenblas.so which I similarly assume addresses the “no openblas in java.library.path” error also.

Having found these files in the uber jar,

  1. Is there a way Maven can be made to place them in the correct directory upon compilation/building, if the incorrect directory location should be what is what’s causing Java from being able to execute the compiled program/jar file?

  2. Or can they be placed in the “java.library.path” that the error and debugger messages mention?

Otherwise, I am confused as to why Maven doesn’t know that the files are already included/packaged in the uber jar. Thanks.

I tried compiling/building the project using the following commands you initially suggested:

mvn -Djavacpp.platform=linux-armhf package
mvn -Djavacpp.platform=linux-arm64 package
mvn -Djavacpp.platform=android-arm package
mvn -Djavacpp.platform=android-arm64 package

All 4 compile/build without errors, but yield the same 4 errors I mentioned previously.

Saudet recommended taking a look inside the compiled uber jar to see if the indicated libraries were in there or not. Unless I sm mistaken, they are in there, but not in the “org/bytedeco…” directory. They are rather located in “lib/armeabi-v7a/…” The jnijavacpp file is specifically located in “lib/armeabi-v7a/libjnijavacpp.so” as are the other files that yielded the errors.

I’ve asked Saudet if there’s something that can be done in order to compile/build my project to an uber jar file so that the uber jar recognizes the “missing” files.

I’ll check out your other recommendation on building an android application in the meantime too. Thanks.

Right, Android has its own loader for native libraries, but they need to be under /lib/.... JavaCPP won’t try to load them by default because that conflicts with Android. Since you’re not using Android’s version of Java though, you’ll need to enable that. Setting the “org.bytedeco.javacpp.pathsfirst” system property to “true” should do the trick.

1 Like

Sounds good. How exactly do I set “org.bytedeco.javacpp.pathsfirst” to true? I assume this would be done in the building step, not the execution step? Thanks.

Same as the other one above: Trouble Installing on Android Device Running Arm Processor - #16 by saudet

I tried setting “org.bytedeco.javacpp.pathsfirst” to true in the following manner when executing the program:

java -Dorg.bytedeco.javacpp.pathsfirst=true -cp deeplearning4j-example-sample-1.0.0-beta7-bin.jar org.deeplearning4j.examples.sample.LeNetMNIST

but it still returned the same four errors:

  1. Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
    Exception in thread “main” java.lang.ExceptionInInitializerError
  2. Caused by: java.lang.RuntimeException: ND4J is probably missing dependencies. For more information, please refer to: https://deeplearning4j.konduit.ai/nd4j/backend
  3. Caused by: java.lang.UnsatisfiedLinkError: no jniopenblas_nolapack in java.library.path
  4. Caused by: java.lang.UnsatisfiedLinkError: no openblas in java.library.path

I had previously built my program in the following way, which yielded a “BUILD SUCCESS” message:

mvn -Djavacpp.platform=android-arm package

Thanks.

Also set org.bytedeco.javacpp.logger.debug…

I went ahead and included it in the following manner:

java -Dorg.bytedeco.javacpp.logger.debug=true -Dorg.bytedeco.javacpp.pathsfirst=true -cp deeplearning4j-example-sample-1.0.0-beta7-bin.jar org.deeplearning4j.examples.sample.LeNetMNIST

I even tried reversing the order of the Java debugger and the pathsfirst properties to see if that made a difference, but it didn’t:

java -Dorg.bytedeco.javacpp.pathsfirst=true -Dorg.bytedeco.javacpp.logger.debug=true -cp deeplearning4j-example-sample-1.0.0-beta7-bin.jar org.deeplearning4j.examples.sample.LeNetMNIST

The debugger yielded the following:

Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.javacpp.Loader
Debug: Loading library jnijavacpp
Debug: Failed to load for jnijavacpp: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.openblas.global.openblas_nolapack
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.openblas.global.openblas_nolapack
Debug: Loading library
Debug: Failed to load for : java.lang.UnsatisfiedLinkError: no in java.library.path
Debug: Loading library openblas
Debug: Failed to load for openblas: java.lang.UnsatisfiedLinkError: no openblas in java.library.path
Debug: Loading library jniopenblas_nolapack
Debug: Failed to load for jniopenblas_nolapack: java.lang.UnsatisfiedLinkError: no jniopenblas_nolapack in java.library.path

I keep on seeing the “UnsatisfiedLinkError” which I looked up and resources suggest including in java.library.path the directory address of where the .so files that are failing to load are located. In your experience, is this something you’ve personally encountered before in working with DL4J? Thanks.

What does Loader.getPlatform() return?

Do I do “Loader.getPlatform” within a small Java program as in?:

System.out.println(Loader.getPlatform());

Yes, what does that print out?

When I run System.out.println(Loader.getPlatform());, what prints out is: android-arm

When I build the project, I specifically use: mvn -Djavacpp.platform=android-arm package
which builds the project successfully with no errors.

Both my build command and the getPlatform() method use/return the same android-arm so I would’ve thought my build selection was ideal.

If there are files like /lib/armeabi-v7a/libjnijavacpp.so in the JAR file, yes, it should work, so something else is going on here… If you can debug Java code, please try to figure out why Loader.findResource(Loader.class, "/lib/armeabi-v7a/libjnijavacpp.so") doesn’t work!

Yes, I do indeed have the exact file /lib/armeabi-v7a/libjnijavacpp.so and others in my uber jar.

Now, in which Java source code file do I specifically look inside to search for the line of code Loader.findResource(Loader.class, “/lib/armeabi-v7a/libjnijavacpp.so”) in order to debug it?

I did not find this Loader.findResource… line of code in the Java source code file (LeNetMNIST.java) of the mvn-project-template project folder.

FWIW, when I run mvn clean compile exec:java -Dorg.bytedeco.javacpp.platform=android-arm -Dorg.bytedeco.javacpp.logger.debug -Dorg.bytedeco.javacpp.pathsfirst inside
https://github.com/bytedeco/javacpp-presets/tree/master/artoolkitplus/samples
it’s finding the libraries just fine and tries to load them (but it can’t because I’m not on Android):

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------< org.bytedeco.artoolkitplus:multimain >----------------
[INFO] Building multimain 1.5.4
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ multimain ---
[INFO] Deleting /home/saudet/projects/bytedeco/javacpp-presets/artoolkitplus/samples/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ multimain ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/saudet/projects/bytedeco/javacpp-presets/artoolkitplus/samples/src/main/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ multimain ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /home/saudet/projects/bytedeco/javacpp-presets/artoolkitplus/samples/target/classes
[INFO] 
[INFO] --- exec-maven-plugin:3.0.0:java (default-cli) @ multimain ---
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.javacpp.Loader
Debug: Locking /home/saudet/.javacpp/cache before extracting
Debug: Extracting jar:file:/home/saudet/.m2/repository/org/bytedeco/javacpp/1.5.4/javacpp-1.5.4-android-arm.jar!/lib/armeabi-v7a/libjnijavacpp.so
Debug: Loading /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so
OpenJDK 64-Bit Server VM warning: You have loaded library /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.
Debug: Failed to load /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: java.lang.UnsatisfiedLinkError: /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)
Debug: Loading library jnijavacpp
Debug: Failed to load for jnijavacpp: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.javacpp.Pointer
Debug: Loading /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so
Debug: Failed to load /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: java.lang.UnsatisfiedLinkError: /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: /home/saudet/.javacpp/cache/javacpp-1.5.4-android-arm.jar/lib/armeabi-v7a/libjnijavacpp.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)
Debug: Loading library jnijavacpp
Debug: Failed to load for jnijavacpp: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Warning: Could not load Pointer: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.artoolkitplus.global.ARToolKitPlus
Debug: Loading class org.bytedeco.javacpp.presets.javacpp
Debug: Loading class org.bytedeco.artoolkitplus.global.ARToolKitPlus
Debug: Loading library ARToolKitPlus
Debug: Failed to load for ARToolKitPlus: java.lang.UnsatisfiedLinkError: no ARToolKitPlus in java.library.path
Debug: Locking /home/saudet/.javacpp/cache before extracting
Debug: Extracting jar:file:/home/saudet/.m2/repository/org/bytedeco/artoolkitplus/2.3.1-1.5.4/artoolkitplus-2.3.1-1.5.4-android-arm.jar!/lib/armeabi-v7a/libjniARToolKitPlus.so
Debug: Loading /home/saudet/.javacpp/cache/artoolkitplus-2.3.1-1.5.4-android-arm.jar/lib/armeabi-v7a/libjniARToolKitPlus.so
Debug: Failed to load /home/saudet/.javacpp/cache/artoolkitplus-2.3.1-1.5.4-android-arm.jar/lib/armeabi-v7a/libjniARToolKitPlus.so: java.lang.UnsatisfiedLinkError: /home/saudet/.javacpp/cache/artoolkitplus-2.3.1-1.5.4-android-arm.jar/lib/armeabi-v7a/libjniARToolKitPlus.so: /home/saudet/.javacpp/cache/artoolkitplus-2.3.1-1.5.4-android-arm.jar/lib/armeabi-v7a/libjniARToolKitPlus.so: wrong ELF class: ELFCLASS32 (Possible cause: architecture word width mismatch)
Debug: Loading library jniARToolKitPlus
Debug: Failed to load for jniARToolKitPlus: java.lang.UnsatisfiedLinkError: no jniARToolKitPlus in java.library.path

So it looks like everything’s working correctly. Those files are most likely just missing from your JAR file…