Running JNI based code inside XCode
Sometimes you want to run JNI based code inside XCode – e.g. in case when your C/Objective-C/C++ code is based on some Java library.
It’s both simple and little bit confusing to get JNI running in XCode – you have to make sure to set few things before proceeding.
1. Getting source code
In this article I will use one of mine recipes from JNI Cookbook. Note that source code can be found here: GitHub.
> mkdir -p ~/workspace > cd ~/workspace > git clone https://github.com/mkowsiak/jnicookbook
2. Creating new project inside XCode
Start XCode and create new project macOS -> Command Line Tool. Once there, make sure to remove main.m file and replace it with $HOME/workspace/jnicookbook/recipeNo065/c/recipeNo065_main.m. You should have something like this.
3. Adding custom user variable
Make sure to switch to Project -> Build Settings so you can add new, user-defined, variable. I will use JAVA_HOME. It should point to location where your Java is installed. You can get this location by calling java_home
> /usr/libexec/java_home -v 11.0.4 /Library/Java/JavaVirtualMachines/jdk-11.0.4.jdk/Contents/Home
4. Setting up Search Paths
You need to set following search paths: Header Search Path, Library Search Path, and Runpath Search Path. Inside Header Search Path section make sure to add: $(JAVA_HOME)/include/darwin and $(JAVA_HOME)/include. Like this
Inside Library Search Path make sure to set location of libjvm.dylib ($(JAVA_HOME)/lib/server). You can set it following way
Last thing to set here is Runpath Search Path. Make sure to add $(JAVA_HOME)/lib/server there as well
5. Make sure your code is linked with libjvm.dylib
Last thing we have to do (in order to compile the code) is to pass -ljvm to the linker
6. Running the code
Note that JVM uses SIGSEGV to throw exceptions. Make sure to set breakpoint early in your code and ignore SIGSEGV
(lldb) process handle --pass true --stop false --notify true SIGSEGV
7. Continue debugging session
After process handle --pass true --stop false --notify true SIGSEGV is executed inside lldb you can continue with the debugger session.