-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Z3 Java API fails to detect libz3.dylib #294
Comments
Tested on 64bit Debian 8.0, same issue. package example;
public class Main {
public static void main(String[] args) {
System.load("/tmp/z3/build/libz3.so");
System.load("/tmp/z3/build/libz3java.so"); // line 8
}
} The output:
|
Is /tmp/z3/build/ in your (DY)LD_LIBRARY_PATH and or java.library.path? Note that
actually loads
(extra /private) |
Bumping this. Is this still an issue or has this been resolved? |
Since there was no further update on this issue, I assume that it has been resolved and those I'll close it. |
Add an environment variable to your IDE's run configuration. e.g. for a mac, DYLD_LIBRARY_PATH = "path/to/z3/lib" |
´I still have the problem. I have defined the DYLD_LIBRARY_PATH as well as java.library.path. I still get the exception. I have added debug code that prints the java.library.path and it comes out correctly. Here is an interesting observation: if I run the program from the directory that contains the dylib, then it works. As soon as I start from a different directory, using DYLD_LIBRARY_PATH and java.library.path to try to find the native libs, it does not work. Here is the exception I get: $ java -cp ./bin/com.microsoft.z3.jar:. -Djava.library.path="/Users/markusvoelter/Downloads/z3-4.4.1-x64-osx-10.11/bin" JavaExample If I now rename libz3java.dylib to liblibz3java.dylib, it seems I get one step further. I get the following exception: Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/markusvoelter/Downloads/z3-4.4.1-x64-osx-10.11/bin/liblibz3java.dylib: dlopen(/Users/markusvoelter/Downloads/z3-4.4.1-x64-osx-10.11/bin/liblibz3java.dylib, 1): Library not loaded: libz3.dylib Not it seems it can load libz3java.dylib but now misses libz3.dylib. |
Did you make sure that both, Java and Z3 are both 64-bit? They must be the same, otherwise the error message might just say 'can't find' or 'can't load'. |
Wow, thanks for your quick reply!! I have downloaded this Z3: And my Java outputs: |
Also, could you try a more recent nightly binary? The 4.4.1 release is already a few months old. Or even better, compile it from source. |
Ok, I rebuilt from sources. Same problem. If I run the JavaExample from its directory with the following command $ java -Djava.library.path=../../build -cp ../../build/com.microsoft.z3.jar:. JavaExample I still get the exception: Exception in thread "main" java.lang.UnsatisfiedLinkError: no libz3java in java.library.path This happens irrespective of whether I define the LD_LIBRARY_PATH or DYLD_LIBRARY_PATH or not. |
Yes, the Java API is only built with --java added to python scripts/mk_make.py. Can you confirm that there is a file called libz3java.dylib? |
This seems to be a Mac-specific problem. We just ran the same tests on Windows and on a Mac: on WIndows, it works, on the Mac the tests fail with the exception I reported above. |
I have debugged into this a little bit futher; specifically, I have added print statements to the code that loads the library:
When I run this, I get
So it tries to load z3java, which I think initially succeeds. But then that lib tries to load libz3.dylib, which fails. At this point, the whole loadLibrary call for z3java fails, and the system tries to load libz3java (which I think triggers liblibz3java), because a "lib" is automatically prepended. If I create a copy liblibz3java.dylib of ibz3java.dylib, then the initial loading succeeds, and I get the same
as before. So we can conclude: it is not the initial loading of libz3java that fails, but rather, the subsequent loading of libz3.dylib. |
Ok, I have found the problem. It is (once again!!) Apple's security crap causing problems: If you turn of SIP, the library is loaded correctly. While I was able to do this, requiring our end users to do this is going to be essentially impossible. Any chance this can be fixed with some kind of workaround? |
Wow, thanks for getting to the bottom of this and reporting it back! It never even crossed my mind to check any system features like SIP, so that would have taken me ages to figure out. Definitely an opportunity to improve error messages, but I'm not sure that we can do anything about that on our end. |
A good error message would of course help. A workaround seems to be to put the dylib into the working dir of the process: loading still works, only the DYLIB.... path seems to be ignored. |
Here is the openJDK bug for the underlaying issue. It contains some recommendations. Not sure if any of them works here: https://bugs.openjdk.java.net/browse/JDK-8139288 |
I did some extra investigation and found a solution which works with SIP enabled. When java loads a dynamic library it only looks at the locations in java.library.path.
Important: it seems that Java LoadLibrary first looks in
I tested this on os x, and there it seems to look first at working directory! Normally when an exectutable or library loads a dynamic library it looks at location specified by the operating system.
Note that above fixed locations are the locations set in the default value for DYLD_FALLBACK_LIBRARY_PATH. These locations are still used when SIP is enabled as I found by the following reference:
So for z3 above @markusvoelter concluded that it is not the initial loading of libz3java that fails, but rather, the subsequent loading of libz3.dylib. Loading of the JNI library succeeds because @markusvoelter set the java.library.path explicitly on the commandline in its test. However subsequent loading of libz3.dylib by libz3java.dylib fails because:
So the quickfix is to move or link libz3.dylib in ~/lib. Personally I'm the only user of my macbook and prefer not to put libraries in my homedir, so I prefer the solution :
Note: to preserve the original installation I prefer soft linking into the original installation locations which also works fine. However if you would have different versions of a library then with above central installation we have a problem because we can only link one version! In that case you add the dynamic link libraries at working directory ($CWD ) of each specific program. This works because as specified above for both jni and none-jni dynamic libraries are searched first at the current working directory of the current process. A completely alternative solution is to relink the subsequent library dependency of libz3.dylib in libz3java.dylib with an absolute path so that it doesn't need a PATH. For how to do this look at: http://thecourtsofchaos.com/2013/09/16/how-to-copy-and-relink-binaries-on-osx/ However personally I prefer to just use the standard, that is use the above standard locations!! |
@harcokuppens Have you tried to get this to work when building with the CMake build system? IIRC CMake does things a little differently (than the old build system). |
No, I didn't used cmake. I just downloaded a prebuild version of z3 from https://github.com/Z3Prover/bin/tree/master/releases . This already contains libz3java.dylib and libz3.dylib . I didn't use the homebrew version on os x because that build doesn't contain libz3java.dylib. Then I just used maven or eclipse to build. But any other java build system should be fine as long you put the dynamic libraries on the right locations mentioned in my previous post. However from your post it is not clear what exactly you are building? Are you building z3 with cmake, or are you building a java project with cmake which uses z3 as library? Anyway what I do know is that for java builds you cannot use DYLD_LIBRARY_PATH because the java executable is a SIP protected file. Source: conda-forge/staged-recipes#913 (comment)
You can see whether a binary is SIP protected by the following command :
where restricted means protected by SIP.
So cmake is not restricted and not protected by SIP. So what I understand from the apple documentation you can then use the DYLD_LIBRARY_PATH environment variable without any problems. However I must say I didn't test this with cmake, but above quote seems to say it should work with cmake. Apple documentation about SIP However in general I would just use the standard install locations for .dylib files and don't rely on DYLD_LIBRARY_PATH for installations anymore. However for developer builds it can be convenient to use DYLD_LIBRARY_PATH, and then it maybe convenient to use cmake from homebrew. |
Facing the same issue I have tried all the solutions mentioned above. Need help to identify where I'm going wrong. Java --version lrwxr-xr-x 1 root wheel 58 Nov 8 22:15 liblibz3java.dylib -> /Users/dhanu/Documents/Covlant/z3/z3/build/libz3java.dylib trying to load lib z3java I have tried directly passing the lib location too nothing worked. Thanks in advance for the help. |
This is a crosspost of an issue reported here: https://stackoverflow.com/questions/33541226/z3-java-api-fails-to-detect-libz3-dylib
When running Z3 via the Java wrapper, the libz3.dylib library is not recognised by libz3java.dylib.
Trying to load the library by hand results in the following behaviour:
The output:
This may or may not be related to the recent OS X upgrade, but I have no evidence for it.
The text was updated successfully, but these errors were encountered: