`
nanapoleon
  • 浏览: 48029 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

本地方法调用1

阅读更多
啊,好久没写blog了,更新还真是不适应。这个。。。话说,婚假回来,就一直没有感觉,虽然现在感觉也不是很好,但还是要hold住~
今天开始要搞一搞jni了,不然一年也屡不清原计划啊。
java的书从来都说的很好,100%纯java的解决方案是非常好的,但是,java性能真的还是不如c和c++。一般的辩解会是:网络io才是真正的瓶颈等等云云。ok,没错,但是(当然要有但是啦。一?这句话怎么这么熟?),java的速度确实不如c和c++,导致在很多时候,如用户响应上,确实有时会有不顺畅的感觉。当然,瑕不掩瑜,在很多时候,java还是非常强的,并且很难替代。
今天,先来一节入门篇,讲讲如何从java调到c函数的。
首先是native申明。
native声明一个方法后,就不用再写方法体了,因为实现是在下面进行。
来看看code:
class HelloNative{
    public static native void greeting();
}

注意,static不是必须的。
你实际可以使用这个类,但是在程序中使用它时,虚拟机就会告诉你它不知道如何找到greeting,它会报告一个UnsatisfiedLinkError异常。为了实现本地代码,需要编写一个响应的c函数,你必须要完全按照java规则来命名这个函数:
1)使用完整的java方法名,比如:HelloNativ.greeting。如果类输入某个包,那么前面添加报名,比如:com.horstmann.HelloNative.greeting。
2)用下划线替换掉所有的句号,并加上Java_前缀,例如,Java_HelloNative_greeting或者Java_com_horstmann_HelloNative_greeting。
3)如果类名含有非ASCII字母或数字,如:‘_’,‘$’或是大于‘\u007f’的Unicode字符,用_0xxxx来替代它们,xxxx是该字符的值的4个十六进制数。
(注意,如果有两个方法 greeting()和greeting(int i),那么必须在后缀附加两个下划线,后面加上已编码的参数类型:Java_HelloNative_greeting__和Java_HelloNative_greeting__I)
很麻烦吧?别紧张,这些东西,是能够自动生成的,先使用javac对java文件编译,然后使用javah,生成如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */

#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloNative
 * Method:    greeting
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

接下来我们只用在HelloNative.c的文件中实现这个声明了的方法就好了:
#include "HelloNative.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv* env, jclass cl){
    printf("hello native world!\n");
}

C++也是可以的:
extern "C"
JNIEXPORT void JNICALL Java_HelloNative_greeting
  (JNIEnv* env, jclass cl){
    cout<<"hello native world!"<<endl;
}

ok,我们可以把这个.c文件在linux下编译了,命令:
gcc -fPIC -I jdk/include -I jdk/include/linux -shared -o libHelloNative.so HelloNative.c

好了,生成的so就可以使用了,当然,为了确保虚拟机第一时间把库load进去,我们要使用静态初始化代码块:
class HelloNativeTest{
    static{
        System.loadLibrary("HelloNative");
    }

    public static void main(String[] args){
        HelloNative.greeting();
    }
}

在linux在,必须把当前目录添加到库路径中。实现方式可以通过设置LD_LIBRARY_PATH环境变量:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
或者是设置java.library.path系统属性
java -Djava.library.path=. HelloNaticeTest
好了,java可以找到我们了。

一些本地代码的共享库必须先运行初始化代码。你可以把初始化代码放到JNI_OnLoad方法中。类似的,如果你提供该方法,当虚拟机关闭时,将会调用JNI_OnUnload方法。
它们的原型是:
jint JNI_OnLoad(JavaVM* vm, void* reserved);
void JNI_OnUnLoad(JavaVM* vm, void* reserved);
OnLoad返回所需的虚拟机的最新版本,如:
JNI_VERSION_1_2.

现在,从上到下的调用都讲明白了,下次,我们再继续深入吧。
分享到:
评论
3 楼 nanapoleon 2012-06-05  
test_angel 写道
test_angel 写道
我在编译so库的时候报以下错误:指点指点

error: expected constructor, destructor, or type conversion before ‘void’



我知道原因了:jni.h的位置没有给正确。现在已经可以了!

好吧,刚看到你的留言。。。
2 楼 test_angel 2012-06-04  
test_angel 写道
我在编译so库的时候报以下错误:指点指点

error: expected constructor, destructor, or type conversion before ‘void’



我知道原因了:jni.h的位置没有给正确。现在已经可以了!
1 楼 test_angel 2012-06-04  
我在编译so库的时候报以下错误:指点指点

error: expected constructor, destructor, or type conversion before ‘void’

相关推荐

    C++本地方法调用

    调用iphlpapi获得本地ip信息,C++源代码演示获取ip信息的全过程。

    JAVA通过本地方法调用C例子

    本案例将详细讲解如何在Java中通过本地方法调用C语言实现的功能,具体以一个调用系统时间的简单例子进行说明。 首先,我们来看`TimeShow.java`这个Java类,它通常包含了一个native方法声明,例如: ```java public...

    Java语言如何调用C++语言编写的本地方法

    在Java程序中调用用C++语言编写的本地方法,是通过Java本地接口(JNI)实现的,JNI是Java提供的一套标准编程接口,用于Java代码和本地应用程序或库之间的交互。本地库通常是用C或C++编写的动态链接库(在Windows上是...

    Android中调用js方法及js中调用本地方法

    本文将详细讲解如何在Android中调用JavaScript的方法,以及JavaScript如何反向调用Android本地方法。 首先,让我们从Android调用JavaScript的方法开始。Android中的WebView组件是实现这种交互的主要工具。当在...

    JS和Android本地方法之间的调用

    为了实现这种交互,开发者通常需要理解JS与Android本地方法之间的调用机制。本篇将深入探讨这个主题,帮助你更好地理解和实践这两种技术的融合。 一、JavaScript与Android交互基础 1. Webview:Android中的WebView...

    chrome 调用本地exe

    1,chrome 浏览器本身不支持直接调用exe,但可以使用url protocol handler 调用exe 2,直接双击exe_chrome.reg 安装注册表 3,test.html 要在运行在容器里(tomcat,resin XXXX),本地直接打开是执行不了的,我...

    Java本地调用接口 JNative

    Java本地调用接口(Java Native Interface,简称JNI)是Java平台标准的一部分,它允许Java代码和其他语言写的代码进行交互。JNI在很多场景下都扮演着关键角色,比如当需要访问操作系统特定功能、优化性能或者利用已...

    java调用本地打印机

    在Java编程环境中,调用本地打印机是一项常见的任务,特别是在企业级应用中,如报表生成、文档打印等场景。本文将详细讲解如何利用Java API来实现这一功能,以及可能遇到的问题和解决方案。 首先,Java提供了`java....

    web调用本地程序示例

    在IT领域,Web调用本地程序是一种常见的技术需求,它允许网页通过某种方式与用户的本地计算机进行交互,执行特定的任务。这种技术广泛应用于自动化工作流程、远程服务支持、软件更新等场景。本示例提供了实现这一...

    jni本地调用4

    在"JNI本地调用4"这个主题中,我们将深入探讨JNI的使用,特别是在执行本地方法和实现Java与C/C++代码集成时的关键知识点。 1. **JNI概述**:JNI是一个接口,提供了一套API,使得Java开发者可以编写本地方法来调用非...

    Android-一个让http接口调用跟调用本地方法一样自然优雅的项目

    标题提到的“Android-一个让http接口调用跟调用本地方法一样自然优雅的项目”正是为了解决这个问题,它旨在通过自动化的方式使得HTTP接口调用变得更为简洁、直观。 该项目的核心思想是将HTTP API与接口绑定,这样...

    远程方法调用(客户端调用服务端的方法)源码

    这种技术使得分布式计算成为可能,使得开发者可以构建分布式应用程序,使得客户端能够像调用本地对象一样调用远端服务器上的对象。 在RMI中,主要涉及以下几个核心概念: 1. **远程接口(Remote Interface)**:这...

    RMI远程方法调用RMI远程方法调用

    RMI的核心理念是让开发者能够像调用本地方法一样调用远程对象的方法,简化了分布式系统的设计和实现。 **什么是RMI** RMI(Remote Method Invocation)是一种Java技术,它提供了在不同网络节点上的Java虚拟机之间...

    js调用android本地方法的实现

    1. **JS端**:封装调用Android方法的JS函数,将调用信息打包成消息。 2. **Android端**:解析来自JS的消息,执行相应的原生方法,并将结果返回给JS。 3. **通信机制**:处理消息传递,如通过`postMessage`和`...

    windows下浏览器调用本地应用程序

    总的来说,Windows下浏览器调用本地应用程序的方法包括使用ActiveXObject(仅限IE)、创建.url快捷方式和注册自定义URL协议等。需要注意的是,这些方法都涉及对用户计算机的访问,因此在实际应用中必须谨慎处理,以...

    java调用c代码:AVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式 )。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法

    1. **在Java中声明本地方法**: 首先,你需要在Java类中声明将要调用的本地方法。这些方法需要使用`native`关键字,并且不需要提供具体实现。例如: ```java public class TestDLL { static { System....

    使用Python调用微信本地ocr服务.zip

    使用Python调用微信本地ocr服务.zip使用Python调用微信本地ocr服务.zip使用Python调用微信本地ocr服务.zip使用Python调用微信本地ocr服务.zip使用Python调用微信本地ocr服务.zip使用Python调用微信本地ocr服务.zip...

    java远程方法调用

    - 性能开销:远程调用涉及序列化、网络传输等操作,性能不如本地调用。 - 复杂性:实现和维护较为复杂,尤其是处理异常情况时。 #### 六、总结 RMI为Java开发者提供了一种强大的工具,用于构建分布式应用。理解RMI...

    通过Java调用本地方法.pdf

    1. 编写本地方法声明类,例如WinMsgBox.java。 2. 编译生成字节码,例如WinMsgBox.class。 3. 利用JNI生成头文件,例如WinMsgBox.h。 4. 根据头文件编写实现代码,例如WinMsgBox.c。 5. 编译生成动态连接库文件,...

Global site tag (gtag.js) - Google Analytics