- 浏览: 295279 次
- 性别:
- 来自: 湖南
文章分类
最新评论
-
lliiqiang:
枚举类型可以在父类中根据instanceof强制判断是否是指定 ...
JEditorPane显示HTML中文乱码 -
jiangsulane911:
下载了你提供的文件,解压后将RXTXcomm.jar 放到 ...
运行在 mac 10.6 上出现的异常 -
hxcan:
非常感谢。
linux 启用root用户登录 -
wshxx998:
请问你的在配置SDK路径的时候使用的是root帐号还是普通帐号 ...
android sdk linux 1.5 安装与配置 -
finux:
不如使用JFormattedTextField.setForm ...
JTextField 只能输入限定的数字
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");
}
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");
}
发表评论
-
vsftpd 搭建 - 添加用户
2010-08-24 21:02 1921纲要: 一, VsFTPd的简述 二, 企业Linux下vsF ... -
linux 打开pdf 文件
2010-07-16 21:19 1788... -
Fedora Core 5.0 中添加字体及应用程序字体设置方法
2010-05-19 23:35 1639Fedora Core 5.0 中添加字体及应用程序字体设置方 ... -
Fedora文字模式界面下安装中文字体
2010-05-19 23:34 2230FC9安装simsun字体,将windows下的字体simsu ... -
MAC OS X DNS 服务器
2010-04-23 22:19 1413要查明您应该使用哪个 DNS 服务器,请联系您的 ISP 或网 ... -
ssh demo
2010-02-01 23:03 1604ssh demo war包 自己保存使用 -
linux下mysql乱码问题
2010-02-01 22:45 920和windwos中的Mysql一樣,默認的設置都是latin1 ... -
Linux下Tomcat的安装
2010-01-31 22:19 952Linux下Tomcat的安装 可 ... -
下载MySQL的安装
2010-01-31 22:10 1183二、安装Mysql 1 ... -
VNCServer 配置 及Vncview的使用
2010-01-08 00:06 4116VNCServer 配置 及Vncview的 ... -
Linux中的远程连接
2010-01-07 23:21 1530我们知道在windows下面我 ... -
linux下安装输入法 ibus
2010-01-07 21:57 3093在fedora 下安装 ibus 网上的大鸟给误导了说什么 ... -
VNC Server 在 Linux 下的安裝
2009-11-30 23:56 2263遠端控制一直是個理想的工作目標,你不但可以在本機使用電腦,在離 ... -
SSH 连接 Ubuntu 时的中文乱码问题
2009-11-21 09:30 2464若使用 Ubuntu 中文系统,其默认将使用 UTF-8 作为 ... -
Ubuntu服务器上SSH Server 的安装和设置
2009-11-21 09:28 25021.在sshd的设置文件/etc/ss ... -
android sdk linux 1.5 安装与配置
2009-11-15 01:55 84121.下载android sdk 下载地址如下: http:// ... -
linux 启用root用户登录
2009-09-25 23:55 65149Ubuntu Linux有一个与众不同的特点,那就是初次使用时 ... -
linux 中swing 显示乱码问题
2009-09-23 23:18 3808第二部分:问题定位 Linux下Java程序界面中中文显示 ... -
在Windows上构建Linux系统——后传二:用光盘部署目标系统
2009-09-08 23:55 1381在部署用Windows系统构建 ... -
linux 问题 mkisofs
2009-09-07 21:17 2077apt -get install mkisofs The pr ...
相关推荐
jni调用实例,适合初学者,能用,可以试试,有问题可以提
这是Android的NDK开发之Android JNI调用流程程一个demo。下载下来可以直接在android studio上运行。
Android Studio两个工程中:一个使用jni可以编译成so,一个app中加载so,调用jni的接口
完整的实现java跨平台调用C程序源码,包含JAVA源码和C源码以及编译后的demo dll。将dll放到jdk bin目录下,java 项目可以直接运行。若要修改dll可以,修改C源码后重新编译生成dll。该demo处理了多线程调用c,全局...
NDK的配置过程在这里就不讲了,这个demo主要实现的是通过jni技术,我们让java调用c代码。
Android上编写Native jni调用,java调用c ,c调用java。
本例子用java实现调用动态库的例子,JNI调用。
简单的jni本地调用demo,欢迎下载,生成.h文件,然后用ndk-build命令生成.so文件,最后调用。
Android 通过JNI调用C语言完整示例程序。Android Studio项目工程。
JNI调用C++代码和C++层回调java层 demo
Java通过JNI调用C++接口,Demo文档描述(里面有代码),里面有Windows下调用版和linux下调用版,经本人亲自测试,可用。
Java通过JNI调用C函数Demo 需要的人下载看看
JAVA通过JNI调用C++代码函数的示例DEMO
java 调用 dll 的方法,即JNI的使用,demo中有get()/set()方法,操作步骤详细,即使是没用过java的程序员按照步骤依然可以成功。
一个JNI调用的小Demo。希望使你了解JNI的使用
android jni native C++访问java层数组,java类对象属性和方法,回调接口和线程回调接口 内附可以正常使用的demo
Android 开发中JNI的使用总结, JNI是Java Native Interface 的缩写,意为java本地接口, 使用JNI技术可以使得java语言与其它...Android系统中的JNI运行通常是在java语言开发的apk或其它组件中调用C/C++开发的底层 模块。
这是我的博客使用JNI调用C代码>里面用到的demo 原文地址:http://blog.csdn.net/u013210543/article/details/52103015
JNI入门Demo1.0,用于演示Java代码是如何调用到C++代码