`
zengxx1989
  • 浏览: 300362 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

JNI 调用demo

阅读更多
Here is the quick overview of this example.

HelloWorld.java This is a trivial class with one method, but what makes the method special is the native keyword. This tells the Java compiler that the function is implemented in native code. Other Java classes that access this method are unaware that it is not a Java method.
class HelloWorld {

    // The native keyword is required by the compiler
    // to indicate that the function is implemented
    // in a shared library somewhere.

  public native void displayMessage();

    // Code within the static section is executed
    // when this class is initialized. Since part of
    // the functionality of this class resides in
    // a shared library, it must be loaded at runtime
    // when this class is initialized.

  static
  {

      // The shared library that contains the implementation
      // of the native methods is loaded here. The name of the
      // shared library file is arbitrary, but it is a good
      // idea to give it a meaningful name.

    System.loadLibrary("HelloWorldImp");

  }

}
Main.java This is simply the driver program for testing the native method in HelloWorld.java. Notice that this class is not required to do anything special in order to invoke a native method. In fact, the class is not even aware that the method is implemented in C++ and resides in a shared library somewhere.
class Main {

  public static void main(String[] args)
  {
      // Nothing unusual here. A HelloWorld object
      // is created and a public method is invoked.

    HelloWorld hello = new HelloWorld();
    hello.displayMessage();
  }

}
HelloWorld.h This is the header file generated by the javah tool that is part of Sun's JDK. This file is compatible with both C and C++ compilers. The first line after the initial comment includes the jni.h file. This is why you may never need to include jni.h yourself.
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     HelloWorld
* Method:    displayMessage
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
Notice how the name of the method has been "decorated" with two additional items:
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *, jobject);
The first item, Java, is prepended to the name and is required for all functions. The second item is the name of the Java class, HelloWorld, where this method is declared. Finally, the name of the method appears. Underscores separate the parts. This is one of the reasons you don't want to create this header file manually. It is too easy to forget about little details like this, and leaving these embellishments off will render your program non-functional.
In addition to the modification of the function's name, there are also two other tags that have been applied to the function. These are JNIEXPORT and JNICALL. Basically, these two tags allow the function to be located in the shared library at runtime and are required.

JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)
There are two other points of interest in this header file. The first point to notice is the function's arguments. As you recall, the displayMessage method declared in the Java code did not have any arguments. What gives? Every native method has two additional hidden arguments. The first argument is a pointer to the JNI runtime environment. Basically, it allows the functions to make callbacks into the JVM. You will see this used in more detail later. The second argument is a pointer to the object that called this function. In essence, it is like the this pointer in C++. Even if your functions never need to access either of these, you must still include them in the argument list for the function.

The second noteworthy point is the Signature: portion of the comment.

/*
* Class:     HelloWorld
* Method:    displayMessage
* Signature: ()V
*/
This comment is also generated automatically and can help you to understand how Java types map to C/C++ types. There are two parts to the signature. The first part is enclosed within the parentheses and represents the number and type of arguments to the function. In this case, there were no arguments, so there is nothing between the parentheses. The second portion follows the closing parenthesis. Since the function didn't return anything (a void function), its type is V. Here's a list that maps Java types to signature characters:
Type Chararacter
boolean Z
byte B
char C
double D
float F
int I
long J
object L
short S
void V
array [

For example, a method that takes a double and a byte, and returns a boolean, would have the signature (DB)Z.
To specify an array, the "[" character is followed by the signature character (e.g. an array of floats would be "[F".)

To specify an object, the "L" is followed by the object's class name and ends with a semi-colon, ';' (e.g. the signature for a String is "Ljava/lang/String;".)

HelloWorldImp.cpp This file contains the implementation of the native method declared in the Java code. The easiest (and safest) way to make sure that you have the correct function name and signature is to copy it from the header file created by javah. Since this method is trivial, there is only one exectuable statement. If the Java class HelloWorld had declared other native methods, they, too, would all be implemented in this C++ file.

#include <stdio.h>
#include "HelloWorld.h"   // this header file was generated by javah
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)
{
  printf("Hello World!\n");
}

Common mistakes. Until you get used to the details, you are likely to make a few mistakes. The most common mistake generates an error message like this at runtime:
java.lang.UnsatisfiedLinkError: no HelloWorldImp in shared library path
There are several reasons why this message may be encountered.
The shared library is named incorrectly. In order for the Unix OS to find the shared library at runtime, shared libraries should be named like libXXX.so where XXX is the name of the Java class (HelloWorldImp in the example.) Under NT, the libraries are called Dynamic Link Libraries (DLL) and should be named XXX.DLL (where XXX is the name of the Java class.)
The shared library is not in the search path. Make sure to move the shared library into a directory in the search path, or add this shared library's path to the search path. The environment variable to modify is LD_LIBRARY_PATH under Solaris.
The Java class is loading the wrong library. Make sure that the library being loaded in the static section of the Java class, via the System.loadLibrary(...), is loading the correct library. DO NOT include the lib, .so or .DLL tags. That is done automatically by the OS.
static
  {
    System.loadLibrary("HelloWorldImp");         // correct
    System.loadLibrary("HelloWorldImp.DLL");     // WRONG!
    System.loadLibrary("libHelloWorldImp.so");   // WRONG!
  }
Another common error message is:

java.lang.UnsatisfiedLinkError: displayMessage
This indicates that the shared library has been found and properly loaded, however the specified function (displayMessage here) cannot be located in the library. This is generally an indication that there is a mismatch between the method's signature in the Java code and the signature in the native code. For example, both functions below will compile (probably without any warnings) but at runtime, if the second function is what is implemented, it won't be found by the OS:
// Correct. This function will be located by the OS at runtime.
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage
               (JNIEnv *env, jobject obj)
{
  printf("Hello World!\n");
}

  // WRONG! Extra parameter. This doesn't match the declaration
  // and therefore, at runtime, OS will not be able to locate
  // the function being called by the Java code.
JNIEXPORT void JNICALL Java_HelloWorld_displayMessage
               (JNIEnv *env, jobject obj, int extraParam)
{
  printf("Hello World!\n");
}
分享到:
评论

相关推荐

    Jni调用Demo

    本示例“Jni调用Demo”为初学者提供了一个实践JNI调用的简单教程。 首先,理解JNI的基本概念是必要的。JNI接口定义了一组函数和数据类型,使得Java代码能够声明并调用本地方法(即非Java代码),同时本地方法也能...

    android jni调用demo

    本项目“android jni调用demo”是一个实际操作的例子,它提供了在Android Studio环境中运行的完整流程。 首先,我们需要理解JNI的基本概念。JNI是Java平台的一部分,允许Java代码与其他编程语言(如C/C++)进行通信...

    Android Studio JNI 调用demo

    本示例"Android Studio JNI 调用demo"将展示如何在Android Studio中创建、编译JNI代码,并在Android应用中加载和调用本地库(SO文件)。 1. **JNI基础知识** JNI是Java平台的标准组成部分,它定义了一组API,让...

    JAVA项目JNI调用dll实现DEMO源码,C++&JAVA

    完整的实现java跨平台调用C程序源码,包含JAVA源码和C源码以及编译后的demo dll。将dll放到jdk bin目录下,java 项目可以直接运行。若要修改dll可以,修改C源码后重新编译生成dll。该demo处理了多线程调用c,全局...

    JNI,java调用c Demo

    通过查看和运行这个项目,你可以更深入地理解JNI的工作流程,以及如何在实际的Android应用中使用JNI调用本地代码。 JNI的使用虽然增加了代码的复杂性,但它提供了与Java平台交互的强大能力。例如,它可以用于优化...

    JNI-DEMO.zip_DEMO_JNI DEMO_java JNI Demo_jni_leveldb jni demo

    总之,"JNI-DEMO"项目提供了一个Java使用JNI调用本地库的实例,其中涉及到的关键技术包括Java的`native`方法、`System.loadLibrary()`加载动态库以及通过JNI调用LevelDB的C++ API。这个DEMO对于初学者来说是一份宝贵...

    JNI入门Demo3.0

    JNI在Android开发中尤为重要,特别是在需要调用C/C++原生代码以提升性能或者利用现有库时。本教程“JNI入门Demo3.0”主要针对的是JNI的动态注册Native函数这一核心概念。 首先,我们需要理解什么是JNI。JNI是一种...

    Java JNI调用动态库(Linux、Windows)的实现步骤

    ### Java JNI调用动态库(Linux、Windows)的实现步骤 #### 一、概述 Java Native Interface (JNI) 是一种标准的 Java 接口,它允许 Java 代码和其他语言(如 C 或 C++)编写的代码进行交互。通过 JNI,Java 应用...

    Android JNI demo

    3. 实现本地方法:在C/C++源文件(如`JniDemo.cpp`)中,根据生成的头文件实现本地方法。例如: ```cpp #include "JniDemo.h" void Java_com_example_JniDemo_doSomething(JNIEnv *env, jobject /* this */) { ...

    JNI实现示例DEMO

    JNI在很多场景下都是必要的,比如调用操作系统API、优化性能关键部分或者利用已有的C/C++库。本DEMO将向你展示如何在Java程序中使用JNI来与本地代码(如C或C++)进行交互。 首先,理解JNI的基本概念至关重要。JNI...

    JAVA通过JNI调用C++代码函数的示例DEMO

    本示例DEMO将详细介绍如何在Java程序中通过JNI调用C++代码函数。 首先,我们需要理解JNI的工作原理。JNI提供了一种方式,让Java虚拟机(JVM)能够调用本地方法,这些方法可以是C、C++或者其他本地语言编写的。JNI...

    Android JNI使用demo

    通过这个"Android JNI使用demo",开发者可以学习到如何在Android应用中创建、调用和管理本地方法,理解JNI的工作原理,从而更好地利用C/C++进行性能优化和功能扩展。随着对JNI的深入理解和实践,开发者可以构建出更...

    jni调用第三方dll最简单的实例

    运行Java应用时,系统会自动加载`JniDemo.dll`,并调用其中的`callDllFunction`方法,进而通过JNI调用第三方DLL。 总结来说,这个实例展示了如何使用JNI调用第三方DLL的基本步骤:在Java中声明native方法,生成JNI...

    JniDemo Android调用C语言

    本项目"JniDemo Android调用C语言"提供了一个完整的示例,展示了如何在Android Studio环境中利用JNI调用C语言代码。 首先,我们来理解一下JNI的基本概念。JNI是Java虚拟机(JVM)和本地代码之间的桥梁,它定义了一...

    JNI DEMO:java jni技术 调用 c/c++ 的dll

    在这个DEMO中,我们看到有get()和set()两个方法,这些都是通过JNI调用C/C++实现的。在Java中,这些方法会声明为native,并且没有具体的实现。然后,使用`javah`工具,根据Java类生成相应的C/C++头文件。在C/C++代码...

    Android下jni开发Demo

    通过这个"Android下jni开发Demo",你可以学习到如何从零开始创建和使用JNI模块,包括编写Java接口、生成头文件、实现本地方法、编译加载库,以及如何在Android应用中有效地调用这些本地函数。这将帮助你提升Android...

    JniDemo_H246分析_DEMO_jni测试_

    在“JniDemo”项目中,我们可以期待看到如何在Android应用中调用H246解析相关的本地函数,以及如何将解析结果反馈到Java层进行处理和展示。 总结来说,“JniDemo_H246分析_DEMO_jni测试”项目是一个学习和实践JNI...

    Java通过JNI调用C++的DLL文件.docx

    Java 通过 JNI 调用 C++ 的 DLL 文件 JNI(Java Native Interface)是一种允许 Java 代码和本地应用程序交互的技术。通过 JNI,Java 应用程序可以调用本地库,反之亦然。本文将详细介绍如何使用 JNI 将 Java 应用...

    android jni实用demo

    这个"android jni实用demo"提供了一个很好的学习平台,帮助开发者深入理解如何在Android应用中使用JNI进行跨语言编程。 JNI允许Android应用在Java代码中调用C/C++函数,反之亦然,这对于性能优化、利用硬件加速、接...

Global site tag (gtag.js) - Google Analytics