How does a JNI DLL search for its dependent native DLL? - java

Say I have JNI.dll. It depends on native.dll. Now my Java application calls System.loadLibrary("JNI").
Will the following folder layout work?
MainFolder
|--main.exe
|--SubFolder
|--JNI.dll
|--native.dll
My guess is, there are 2 levels of dependency resolution.
[Level 1]:
System.loadLibrary("JNI") uses JVM property java.library.path to locate JNI.dll.
[Level 2]:
JNI.dll relies on Windows system mechanism to locate native.dll.
Is this correct?
If I set %_JAVA_OPTIONS% as -Djava.library.path=MainFolder\SubFolder, I think it can cover the search for JNI.dll. But will it cover the search for native.dll, too?
ADD 1
It seems my guess of 2 levels got confirmed from here: How to add native library to "java.library.path" with Eclipse launch (instead of overriding it)
See comment by kevin cline. But the mentioned solution with LD_LIBRARY_PATH environment variable only applies to Linux.
ADD 2
I think I didn't make my question clear. Let me put it this way.
My confusion is: the JNI.dll depends on native.dll. Both of them are not in the main.exe's current working directory. Actually they are in a sub folder of CWD.
If I run main.exe directly, I just need to set the java.library.path = <other path>\MainFolder\SubFolder. Both DLL are found correctly.
But if I run my project from Eclipse, besides setting the java.library.path, I have to put the "\MainFolder\SubFolder" in the %PATH% environment variable.
I just don't know why Eclipse is so different.

1)It searches in the current Directory.
2)System folder typically C:\Windows\System32 (use CSIDL_SYSTEM with shgetspecialfolderpath() to get the rigth folder on the given system)
3)Windows folder (C:\Windows )(CSIDL_WINDOWS with shgetspecialfolderpath() to get the right folder on the given system)
4)All the folders listed under PAth environmnet variable

A similar link: Must I place all dependent DLLs into the JDK's bin folder?
Inspired by this thread:System versus user PATH environmental variable...winmerge works only if I add the path to the user PATH
I start to wonder maybe my User %Path% is too long. So I moved the folder path containing my dependent DLL from the end of User %PATH% to the beginning. It works now!
At first, I conclude that one who implemented the Windows' DLL lookup algorithm has some truncation issue. And I almost consider it as another annoying Windows Bug.
But I wrote another Windows application which has similar DLL dependencies to confirm my guess. That application works fine! So I have to review my conclusion.
I checked my User %PATH% entry one by one, and place the folder to each possible location. And finally, I find the root cause.
I have a C:\MinGW\bin entry in User %PATH%, which happens to contain a
libstdc++-6.dll (977KB) but unfortunately, which isn't compatible
with the one I need (825KB). It only works if I place my folder before MinGW.
Now this issue seems resolved. But another one comes up, do I need to switch back and forth if I want to use both my DLL and the MinGW?

Related

Java System.load(libName) looks for wrong lib name

I've run into a strange behaviour on one of our customers machine when trying to load a JNI library at runtime.
When trying to load a library with
System.load("libtestlibrary.so")
I get a
liblibtestlibrary.so.so: cannot open shared object file: No such file or directory
It seems like the given library name is (wrongly) prefixed with "lib" and suffixed with ".so" and thus our library cannot be found.
This only happens on one machine (AIX 6). I was unable to reproduce this behaviour on our own AIX 6 box using the exact same JRE, so I'm guessing this is caused by some OS settings on the customer machine.
Does anybody have an idea how to turn this off?
You can use either:
System.loadLibrary("libraryname");
It will be properly expanded to system specific notation. Or you can use:
System.load("you_can_have_anything_you_like_here")
In second case, all you need to do is to point to proper location of file. If you are looking for cross system development, you might be interested in packaging your native code inside JAR. Take a look here for a sample code where library is taken from JAR file
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
Also, make sure that other libraries are available in LD_LIBRARY_PATH. Note that java.library.path is only valid for your "first" native lib. If your code uses some other shared libs, you have to either compile with rpath or make sure libraries are visible system wide.
Yet another approach is to go via stub: http://jnicookbook.owsiak.org/recipe-No-018/
In that case, you can load library as you like and do whatever you like (e.g. change native code on the fly).

java.lang.NoSuchMethodError in Genexus

I am using GeneXus Evolution 2 for my project. While I was developing, I got the following error:
HTTPステータス 500 -java.lang.NoSuchMethodError:com.genexus.ModelContext.server2webcli(Ljava/util/Date;)Ljava/util/Date;
I don't know what it is and how to solve this. Any ideas?
A NoSuchMethodError usually indicates that a method (declaration) was there when you compiled the code, but the implementation is missing when you're running it. In most cases, the reason for this is that you had one version of the respective library's JAR file on your class path when compiling, and another, incompatible one when running.
A more detailed answer would require a more detailed question...;-)
Supposing you're using Tomcat as servlet container, look at {Tomcat_Home}/webapps/MyApp/WEB-INF/lib, where MyApp is your app name. There will be a gxclassR.jar file that should match with the version of your Genexus installation. To test if you have the right one:
Assure that there is not other similar lib, like gxclassD.jar, in the same folder. If there is, delete it.
Go to the environment target folder where you're working (from the Genexus DE Menu "Tools -> Explore Target Environment Directory") and look for the gxclassR.zip file. Copy to the WEB-INF/lib folder, rename it to gxclassR.jar replacing actual gxclassR.zip file.
Restart tomcat application to assure that the new gxclassR.jar is being used.
If your object keep failing, then the problem may be the .class associated to your genexus object. Maybe isn't correctly generated/compiled. So, to fix this:
Force the building of the genexus object. For this, try the Build with this only option associated to the object. Activate the Force option for this action, accessing to "Tools -> Options -> Build -> Build with this Only"
Once forced the build, go once again to the environment target folder and look for the .class file/s associated to the object. Usually the name of the file/s matches the name of the object. Look the modification date and confirm that is recently.
Copy this .class files to WEB-INF\classes folder inside your webapp folder.
I think this is good enough info to fix your problem. If not, detail your error a little bit more.
It may also be that the method you are calling does not exist, or exists with different parameters, either by quantity or by type.
Check the date and size of the file gxclassR.zip that is on your web folder inside your KB (Tools -> Explore Target Environment Directory), and compare it with the one used by your web application (folder WEB-INF/lib). If they don't match, replace the one in your web application with the one in your KB.
If you are unsure about it, and would rather GX handle it, delete all the .ver files in your web folder and force a build. That should synchronize all the files to the proper version.

Can't locate a file inside the project

Okay; So I've been using Windows for quite some time, however I've recently moved over to a linux-based operating system. I've ran into numerous issues such as the File-System for Linux being case-sensative. IE: Filename.PNG will not load if you try to load Filename.png.
Anyway, That's not my problem here, and I'm kind-of confused.
Here's my problem, in cropped picture format, code and all.
I've tried varations, such as "/SpriteSheets/tileset.jpg", "assets/SpriteSheets/tileset.jpg"
However, I can't get it to work.
Well it seems your file name is tileset.png and not tileset.jpg.
Print your current path first with a System.out.println(new File(".").getAbsolutePath()) and then try and see where you should point your path in the program.
EDIT: Eclipse usually points your path inside the workspace, I've had trouble with that previously. You can set the runtime path to a different directory; Go to Run configurations, choose your configuration, choose tab Arguments and set the working directory (at the bottom) to a directory of your choosing.

Installing Play! framework on Windows 8.1: What do I add to the path?

I am trying to install Play, and have been going through the tutorial. I have also tried for a couple hours now reading through the installation guide. Yet, I cannot find what it is that I need to add to the environment variables in order to get this to Play to work. I also am a little confused on how javac is suppose to work with this, as my understanding through another video is that I needed to add a path to javac as well.
There is also this question that asks a very similar question, but the terminology is above me, and I would like to not mess this up.
Have you tried running java -version in a command line? When you install the JDK, it will usually set itself up for you, so if that works, you don't need to do anything for it. As for Play, unzip it to some location, eg C:\path\to\playinstall, and then add C:\path\to\playinstall to your PATH environment variable. Alternatively use Typesafe Activator, it runs a UI in a browser that manages everything for you.
Here is my init_play.bat that I run in a console window. Run it once when open a new console, then cd into your play app's directory and do play run...
path=%path%;C:\IanTools\play\play-2.2.1
pause
First of all, I am answering this question for Windows users, and at the time of writing this, I am using Windows 8.1.
So after playing around with this for a while, I ended up thinking I had to delete my entire description of the PATH environment variable, but all you have to do is add to the PATH variable. What needs to be added is the location of your Play folder (which is recommended to be placed in the root), and also add the location of JavaSDK+bin, which should be located somewhere in the Program Files folder. Adding these is a simple copy and paste of the entire location of the folder (found in the browsing bar), and insertion into the PATH variable by editing the variable.
Be sure to go to the end of the value of the variable once clicking on Edit. Then, before pasting the location that was just copied, add a ; after the previous entry. If you accidentally delete anything, (as I did), this could spell out some problems for your computer. If you do delete anything, then Ctrl+z or go so some similar thread (<--- like this one). I hope that this is somewhat of a dummies guide to solving the matter, as several Youtube tutorials and threads did not seem to work entirely for me. Best of luck!

UnsatisfiedLinkError - Unable to load library - Native library not found in resource path

I have the following error at runtime, while trying to run Tess4J:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'libtesseract302': Native library (win32-x86-64/libtesseract302.dll) not found in resource path ([myproject/target/classes/, ...some jars...])
My questions are:
1) What exactly it tries to find and where?
2) Why is it apparently searches for myproject/target/classes/ directory? I set it nowhere.
3) Why is it ignores "native directory path" I set for tess4j.jar in user library descripto in Eclipse? My DLLs are there. If it didn't ignore the path, it would find DLLs.
4) Why is it apparently prepending DLL name with win32-x86-64/? I set this nowhere. Is this standard prefix of some API?
5) What is "resource path"? How to set it?
Like the error says, it's looking for win32-x86-64/libtesseract302.dll in java.class.path. Part of your classpath apparently includes myproject/target/classes.
The prefix represents the platform and architecture of the shared library to be loaded, which allows shared libraries for different targets to be included in the same archive. If JNA cannot find the requested library name in the system load path, then it attempts to find it within your resource path (extracting it, if necessary). So if you put the DLL in a jar file, you'll need to give it the win32-x86-64 prefix in order for it to load.
The "resource path" is nominally your class path; basically anywhere reachable by ClassLoader.getResource().
The error stems from your trying to load 32-bit DLLs in 64-bit JVM. The possible solution is switch to 32-bit JVM; alternatively, use 64-bit Tesseract and Leptonica DLLs.
Had the same issue, sorted with the following lines
System.load("/usr/local/lib/liblept.so.5")
System.loadLibrary("tesseract")
For your case, it might be different libraries but in the end is pretty much the same: just load the libraries that you need manually.
Why don't you use JNA API http://www.java2s.com/Code/Jar/j/Downloadjna351jar.htm to load native library? Once you putted into your project classpath, you add this code
NativeLibrary.addSearchPath("libtesseract302", "your native lib path"); make sure you have this libtesseract302.dll file, normally it is located at windows32 folder.
For example, if your libtesseract302.dll file in somewhere c:/abcv/aaa/libtesseract302.dll then you just set the path like this NativeLibrary.addSearchPath("libtesseract302", "c:/abcv/aaa");
I don't know how windows path look like either c:/abcv/aaa or c:\\abcv\\aaa\\
if you want easier way, just put all your necessary dll file into your windows32 folder, JVM will take care of it.
Another issue might be you were not installing the application correctly or the application version is unmatch with your jar version. try to install the latest application and download the latest jar to try again. Hope it helps :)
I had the same problem and found that this "resource path" is not set by "native directory path" .
You can however add new folders to it by using "Add External Class Folder" in the Library tab, even if this folder does not contain any class file but native library files(like DLL on Windows)
A few days ago I ran into the same error message when trying to load a C++ DLL with JNA. It turned out that the cause was a missing DLL that my DLL depended on.
In my case it was the MS Visual Studio 2012 redistributable, which I then downloaded and installed on the machine and the problem was gone. Try using Dependency Walker to find any missing libraries and install them.
I think an easier way to get around this error would be to revert to an earlier version where you were not getting this error. Right click on the project folder and navigate to local history to revert to an earlier version. I verified this workaround on the android studio installed on Mac OS Big sur.

Categories

Resources