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.”)