Eclipse: Hello World in Java Native Interface on Windows

Google Doc Link for this

15 January 2012

    1. Rationale

To use a single workspace within a single installation of Eclipse to develop a project which consists of source files written in both C and Java with calls between them – on a Windows x86 based development machine. The rationale being to increase the ease of development and automate certain parts of the build processes.

    1. Software Components used

  • Cygwin OR MinGW for compiling C code

  • JDK for compiling Java code

  • Eclipse as the IDE

  • JDT and CDT plugins for Eclipse

    1. Installation Instructions

Make sure you have the following installed. If not, then follow this particular order

  1. Install Java Development Kit (JDK) Standard Edition (SE) for Windows 32bit

  2. http://www.oracle.com/technetwork/java/javase/downloads/index.html

  3. Install Eclipse IDE for Java Developers for Windows 32bit

  4. (This includes JDT)

  5. http://www.eclipse.org/downloads/

  6. Eclipse Eclipse CDT (C/C++ Development Tooling) Plugin

  7. http://eclipse.org/cdt/downloads.php

  8. Install EITHER Cygwin

  9. (During Installation, select the “Devel” option in the Select Packages Window)

  10. http://www.cygwin.com/install.html

  11. OR MinGW

  12. http://www.mingw.org/

  13. BUT NOT BOTH

    1. Java Code

  14. Start Eclipse. Preferably create a new workspace called WorkSpaceEclipseJNI

  15. From the menu select File>New>Java Project

  16. Enter Project Name as 01Java_HelloWorld

  17. Click Next >

  18. Click Finish

  19. In the Package Explorer expand 01Java_HelloWorld

  20. Right click src folder and select New>Package

  21. Enter Name as com.lithiumhead.jni

  22. Click Finish

  23. In the Package Explorer under 01Java_HelloWorld > src right click com.lithiumhead.jni and select New>Class

  24. Enter Name as HelloWorld

  25. Click Finish

  26. Paste the following code into HelloWorld.java

package com.lithiumhead.jni;

class HelloWorld {

public native void sayHello();

static {

System.loadLibrary("HelloWorld");

}

public static void main(String[] args) {

HelloWorld h = new HelloWorld();

h.sayHello();

}

}

  1. From the menu select Run>External Tools>External Tools Configurations…

  2. Highlight Program in the list in the left pane

  3. Press the New button

  4. Enter Name as javah - C Header and Stub File Generator

  5. For the Location browse to locate javah.exe in the JDK installation folder

  6. (will be something like C:\Program Files\Java\jdk1.7.0\bin\javah.exe)

  7. Enter Working Directory as: ${project_loc}/bin/

  8. Enter Arguments as -jni ${java_type_name}

  9. Click Apply

  10. Switch to the Common tab

  11. Select the checkbox next to External Tools under Display in favourites menu

  12. Click Apply

  13. Click Close

  14. Deselect Build Automatically from Project Menu

  15. In the Package Explorer right click 01Java_HelloWorld and select Build Project

  16. In the Package Explorer highlight HelloWorld.java

  17. From the menu select Run>External Tools>1 javah - C Header and Stub File Generator

  18. (This will generate the header file for the C code com_lithiumhead_jni_HelloWorld.h placed in the bin folder of 01Java_HelloWorld Java Project.)

    1. C Code

  19. From the menu select File>New>Project…

  20. Expand C/C++

  21. Highlight C Project

  22. Click Next >

  23. Under Project type, expand Shared Library

  24. Highlight Empty Project

  25. Under Toolchains select Cygwin GCC (or MinGW GCC)

  26. Enter Project name as 01C_HelloWorld

  27. Press Next >

  28. Uncheck Debug. Let only Release remain checked.

  29. Click Finish

  30. If asked for switching Perspective to C/C++, check Remember my decision and click Yes

  31. In the Project Explorer right click 01C_HelloWorld and select New>Source File

  32. Enter Source file as com_lithiumhead_jni_HelloWorld.c

  33. Click Finish

  34. Paste the following code in com_lithiumhead_jni_HelloWorld.c

#include <jni.h>

#include "..\01Java_HelloWorld\bin\com_lithiumhead_jni_HelloWorld.h"

#include <stdio.h>

JNIEXPORT void JNICALL Java_com_lithiumhead_jni_HelloWorld_sayHello(JNIEnv *env, jobject obj)

{

printf("Hello world!\n");

return;

}

  1. Press Ctrl+S to save the C code

  2. In the Project Explorer highlight 01C_HelloWorld

  3. Press Alt+Enter to open the Properties for the project

  4. Expand C/C++ Build

  5. Highlight Settings

  6. Highlight Includes from the list within the Tool Settings tab on the right side

  7. Click Add…

  8. Click File System…

  9. Browse to the include folder in the JDK installation folder and click OK

  10. (must be something like C:\Program Files\Java\jdk1.7.0\include)

  11. Click OK

  12. Click Add… again

  13. Click File System… again

  14. Browse to the include\win32 folder in the JDK installation folder and click OK

  15. (must be something like C:\Program Files\Java\jdk1.7.0\include\win32)

  16. Click OK

  17. Highlight Miscellaneous under Cygwin C Linker (or MinGW C Linker) from the list

  18. On the right side, enter Linker flags as -mno-cygwin -Wl,--add-stdcall-alias

  19. (or just -Wl,--add-stdcall-alias in case of MinGW)

  20. Click Apply

  21. Switch to the Build Artifact tab

  22. Delete the text for Artifact name and type in HelloWorld

  23. Delete the text for Output prefix and keep it empty

  24. Click OK

  25. Right click 01C_HelloWorld in Project Explorer and select Build Project

  26. (this will compile the project)

    1. Running it

  27. Switch to Java Perspective by selecting from the menu Window>Open Perspective>Other , select Java (default) and click OK

  28. In the Package Explorer highlight 01Java_HelloWorld

  29. Select Run>Run As>Java Application

  30. This will create a default run configuration called HelloWorld for the project but at the same time throw up an error as observed in the Console View. This is because the Java Virtual Machine does not yet know the path of the DLL file generated from the C Code.

  31. From the menu select Run>Run Configurations

  32. From the list within the left pane highlight HelloWorld under Java Application

  33. On the right side, switch to Arguments tab

  34. Enter VM arguments as

  35. -Djava.library.path="${workspace_loc}\01C_HelloWorld\Release"

  36. Click Close

  37. In the Package Explorer highlight 01Java_HelloWorld

  38. Select Run>Run As>Java Application

  39. Observe the output in the Console View

    1. References

          • Using Cygwin To Develop Windows JNI Methods

          • by David Caldwell

          • http://www.inonit.com/cygwin/jni/helloWorld/

          • Using The Java Native Interface

          • by Christopher Batty

          • http://www.cs.umanitoba.ca/~eclipse/8-JNI.pdf

          • The Java Native Interface Programmer's Guide and Specification - Getting Started

          • http://java.sun.com/docs/books/jni/html/start.html

          • -mno-cygwin -- Building Mingw executables using Cygwin

          • by Mumit Khan

          • http://www.delorie.com/howto/cygwin/mno-cygwin-howto.html

          • MinGW’s Wikipedia Entry

          • http://en.wikipedia.org/wiki/MinGW

          • Important points to note:

              • “However, because GCC does not supply its own C runtime library, MinGW's C compiler targets Microsoft's old Visual C runtime library, MSVCRT, which was released in 1998 and therefore does not include support for C99 features (let alone all of C89); while targeting MSVCRT yields programs that are as native as possible, the lack of support for C99 has caused porting problems, particularly where printf-style conversion specifiers are concerned.”

              • “MinGW forked from version 1.3.3 of Cygwin. Although both Cygwin and MinGW can be used to port Unix software to Windows, they have different approaches: Cygwin aims to provide a complete POSIX layer that provides emulations of several system calls and libraries that exist on Linux, Unix, and the BSD variants. The POSIX layer runs on top of Windows, sacrificing performance where necessary for compatibility. Accordingly, this approach requires Win32 programs written with Cygwin to run on top of a copylefted compatibility library that must be distributed with the program, along with the program's source code. MinGW aims to provide native functionality and performance via direct Windows API calls. Unlike Cygwin, MinGW does not require a compatibility layer DLL and thus programs do not need to be distributed with source code.”)