Building JNI-based Java Applications under Linux and Cygwin


JNI is the Java Native Interface.  It’s a mechanism in Java for calling C programs (perhaps other languages as well) that provide native functionality.  By native I mean platform specific.  This seems like heresy to Java purists, but in practice I can’t imagine making use of real cross platform capabilities without making use of platform specific features.  If you’ve ever tried to work with process management or do anything complex with filesystems under Java, you’ll understand what I mean.

Important Links


Building JNI applications under Cygwin

What is Cygwin?

Cygwin is a complete Unix-styled environment designed for use under various Windows operating systems. Cygwin provides all the basic GNU-based utilities plus a complete X environment. This allows you to create a tolerable environment under which you can do development work for a completely untolerable operating system (re: Windows).

By using Cygwin you can simulate your Linux desktop in order to do development. Any binary built with Cygwin’s gcc has all (or nearly all) the same functionality you’d find in any POSIX compliant Unix system. The Cygwin dll’s provide any such functionality missing from the Windows libraries.

The drawback to using Cygwin’s gcc compiler, however, is that any binary created with it requires the Cygwin libraries be installed too. This is not something you want to force upon your non-Unix literate customers.  They want native Windows applications.

Despite this drawback, you can still use Cygwin to do develpment work. You just have to take care to build your software in a way that doesn’t depend on Cygwin. As it turns out, that’s not very hard to do.

Differences between Unix and Cygwin

There are few differences between your Unix/Linux environment and Cygwin. From a user perspective, you can essentially run all the tools you’re used to, even under the same desktop environment (if you’re up to the challenge of building GNOME or KDE under Cygwin/X – I fell back to an easier but just as feature rich environment: XFCE).

Differences between Windows and Cygwin

Path references are different between Windows and Cygwin. Windows uses the drive letter prefix (eg C:\) while Cygwin uses the root directory instead (eg /cygwin). This is an important subject because Java and Ant on Windows are Win32 binaries and don’t know about Cygwin’s Unix paths.

When setting up the build environment you have to use the Windows path definitions to find your Java and JBOSS installation directories.

You can access Cygwin directories using Windows paths by first changing into the Cygwin installation directories:

cd C:\cygwin

Under here you will find all the traditional directories like usr, lib, home and etc.

To get to the Windows directories from under Cygwin’s Unix-style paths, you change to the special /cygrdrive directory:

cd /cygdrive/c/

The letter after /cygdrive/ is the drive designation.

What is MinGW?

MinGW is a collection of headers and libraries that make building applications using Cygwin’s gcc capable of being run only with the Microsoft Win32 API. By using MinGW you can remove the requirement for Cygwin’s libraries. However, it also means you’re limited to the Microsoft Win32 API, which means you code (or build system) will have lots of #ifdef’s to handle building under either operating system.

How to install

Both Cygwin and MinGW can be installed by using the graphical installer you can download and run from the Cygwin web site. You will probably need to find the MinGW development tools and enabled them since they may not be installed by default.

Setting up environment

In order to build Win32 API applications (or in our case, the Win32 API based JNI library) you have to tell Cygwin’s gcc to use MinGW. This is done simply by setting the –mno-cygwin command line option to gcc:

gcc –mno-cygwin

This option must be specified for both compiles and linking, so setting GCC=gcc –mno-cygwin is probably the easiest approach. We actually use a number of different options for compiling and linking so the JNI library’s Makefile creates a HEADERS and a LINKARGS variable that includes this option.

Java mods for Cygwin Builds

Under Cygwin, the JNI (Java Native Interface) library we created called JNILibrary doesn’t build because gcc doesn’t know about the type “__int64”. You’ll know you hit the problem if you see something like this:

Building JNILibrary class and header…
In file included from /cygdrive/c/j2sdk1.4.2_12/include/jni.h:27,
from JNICrunch-common.h:25,
from JNICrunchHWInfo.c:31:
/cygdrive/c/j2sdk1.4.2_12/include/win32/jni_md.h:16: error: parse error before “jlong”
/cygdrive/c/j2sdk1.4.2_12/include/win32/jni_md.h:16: warning: data definition has no type or storage class

If you do hit this, then you need to edit /cygdrive/c/j2sdk1.4.2_12/include/win32/jni_md.h and change these lines:

typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;

to:

typedef long jint;
#ifdef __GNUC__
typedef long long jlong;
#else
typedef __int64 jlong;
#endif
typedef signed char jbyte;

This assumes you installed the Java SDK under C:\j2sdk1.4.2_12

Important Links – Note: if the MSDN links move, try searching for Windows API Reference