maven-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stuart Maclean <>
Subject Re: JNI jars dependencies
Date Fri, 04 Jan 2013 19:54:46 GMT
Hi from a newbie.

I too have been fighting with how best to develop maven artifacts 
containing jni parts.  Though I found several useful posts on jni and 
maven , e.g.

in the end I rolled my own solution, something I wanted to avoid.  My 
goal was to produce usable artifacts that worked across platforms, ie 
linux 32 and 64 bit and perhaps windows.  Here's some notes on my 
experiences over the past 3-4 days.  My particular jni effort was to 
'Java-ify' an existing C library.

I isolated the Java classes which had native methods into a single Maven 
module, so producing a single artifact.  I placed the Java sources under 
the regular src/main/java.  In the pom, I used maven-native-plugin to 
invoke javah to produce the headers (jn the default location 
target/native/javah).  In the same pom, I then used the exec plugin to 
invoke make in ./native/${}.  Both of these are bound to the 
compile phase, so a simple


will compile Java, run javah, then locate correct Makefile and run it.

   I then added makefiles to ./native/Linux and ./native/Windows.  In 
the Linux makefile, I used VPATH to locate the C sources in 
${basedir}/src/main/c.  The final .so file (which has no platform/arch 
encoded into its name, ie is just is copied by the make into 
${basedir}/target/classes/META-INF/lib, so the package phase will locate 
the .so at /META-INF/lib/, from which the nifty 
com.wapmx.native loader can unpack it at runtime.

The whole artifact is then named

NAME-${os.arch}-${}  and installed and/or deployed.  this is sort 
of a poor man's AOL (from the nar plugin, which I ended up NOT using).

Then a project/module which depends on this artifact simply uses the 
name above.  It's a bit crude, but for 2 or 3 platforms maximum, I think 
it will be manageable.


the javah invocation could have been done either from Maven or make.  I 
chose to to it in Maven, mostly to avoid duplication across many 
platform Makefiles.

I use the wapmx artifact to extract the native lib from the jar, better 
than requiring LD_LIBRARY_PATH solutions.

My particular jni scenario required that the Java side maintain C 
pointers (in both directions).  Knowing that these would be 64 bits wide 
on 64 bit platforms, I had to use Java longs and jlong in the C code.  
Compiling on 32 bit Linux, I then had to add

ifeq ($(shell uname -m),i686)
# want any warning to raise error, but silence any 64/32 bit conversions
CFLAGS += -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast

to the Makefile to silence the compiler's warnings.  I always compile 
with -Werror (any warning is an error, fail to build)

In the C link phase in my makefiles, I statically linked the C library I 
am wrapping, call it W.  To do this, I used an explicit file name, eg.

cc -o /path/to/libW.a my1.o my2.o

I tried fancy -Wl,-static and -Wl,-shared linker options but it always 
failed to link.  I should point out that I had sources to libW, so could 
configure/make it as desired.

Then my end user (who is handed just a single jar) does not need any at runtime.

Paths I investigated but did not finally use:

having the Java classes containing the native methods (call it A) and 
the actual .so (call it B) as separate Maven modules, as explained in 
the first url above. Then B depends upon A being built so that javah can 
locate .class files, but then how do you run test cases in A, since you 
need native code in B.

I did not use maven-nar-plugin, since as suggested, it is really a Maven 
solution to wider native development.  I had a localised (or so I think) 
jni issue.

I used maven-native-plugin over the antrun-plugin, which apparently 
would also give access to javah (would this require an extra Ant 
build.xml or can this be 'embedded' in the pom???)

Comments, suggestions welcomed


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message