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

本地方法调用3

    博客分类:
  • java
阅读更多
    继续本地调用的相关知识。前面已经讲过了关于java如何调用下面的相关知识,包括如何适配变量,jni调用的方法规范,以及一些jni方法调用的注意事项等等。
    根据前面的介绍,我们可以发现,调用的过程,如果真的使用起来,并没有很顺手,因为仅仅只有参数的向下传递是绝对不够的。我们不仅要下层的代码访问上层的,还要来回调用彼此之间的方法,这样做才够cool嘛。而且才能灵活满足各种需求。就像佛经所说:能进能退,乃真正法器(形容能进能退,进退有度,赵云式的霸气),有木有?
    那先来介绍下访问实例域吧。在java程序中,有很多方法,会使用到类中的全局变量,比如下面的代码:
class Employee{
    double salary = 0;
    
    public void raiseSalary(double byPercent){
        salary += 1 + byPercent / 100;
    }
}

    很常见的方法吧?现在呢,我们要把这个raiseSalary变成一个本地方法。根据前面内容,javah可以生成一个如下方法
JNIEXPORT void JNICALL Java_Employee_raiseSalary(JNIEnv *, jobject, jdouble)

    看到这个方法,你能看出和先前讲得有什么不同么?什么?能进能退?我代表赵云,给你跪了。。。咳,我们看到,有两个不同处,第一个,salary变量是一个Employee的变量,并没有被通过参数传入到c层中。这个我们要稍后重点介绍。还有一个,看看第二个传入参数,可以看到,前面由于使用的是static静态方法,所以,传递进来的是jclass,而这里,我们看到传进来的是jobject。这个也很合理,因为静态方法是没有对象的嘛。
    好了,有java对象传下来,后面就很好想象了,对吧。不过,直接访问要求虚拟机暴露它们的内部数据布局,因此,JNI要求程序员通过调用特殊的JNI函数来获取和设置数据的值。这里我们要使用GetdoubleField和SetDoubleField函数,当然还有其他类型,一般语法是:
x = (*env)->GetXxxField(env, this_obj, fieldID);
(*env)->SetXxxField(env, this_obj, fieldID, x);

    这里,又产生了两个疑问,一个是fieldID是个什么东东?还有,GetObjectField方法返回的对象,我们用什么class定义它?
    先看看FieldID,它是一个特殊类型的值,fieldID表示结构中的一个域。使用GetFieldID函数来获得fieldID。
    jfieldID id_salary = (*env)->GetFieldID(env, class_Employee, "salary", "D");

    字符串"D"表示类型是double。这个后面介绍。
    感觉有点像纹理id有没有?JNI的设计者不想把数据域直接暴露在外,所以,他们不得不提供获取和设置数据域值的函数。为了使这些函数的开销最小化,从域名计算域ID(代价最大的一个步骤)被分解出来作为单一步骤。这样,如果你反复获取和设置一个特定的域,你计算域标示符的开销只有一次。
    第二点,如何得到一个class?jni有两种方式得到class:
   
jclass class_Employee = (*env)->GetObjectClass(env, this_obj);

    FindClass函数可以让你以字符串形式来指定类名(很奇怪的是使用/来代替包分割符号.)
   
jclass class_String = (*env)->FindClass(env, "java/lang/String");

    看起来有点像反射,是吧。(越往后看,其实jni的java层的method调用也是反射的形式,他们分别对应了反射的field和method)
    好了,大概介绍完了如何访问java的域,我们最后做个总结,把开始的方法完全转换成jni层的代码:
JNIEXPORT void JNICALL Java_Employee_raiseSalary(JNIEnv* env, jobject this_obj, jdouble byPercent){
    jclass class_Employee = (*env)->GetObjectClass(env, this_obj);
    jfieldID id_salary = (*env)->GetFiledID(env, class_Employee, "salary", "D");
    jdouble salary = (*env)->getDoubleField(env, this_obj, id_salary);
    salary += 1 + byPercent;
    (*env)->SetDoubleField(env, this_obj, id_salary, salary);
}
分享到:
评论

相关推荐

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

    Java本地调用接口 JNative

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

    chrome 调用本地exe

    3,test.html 要在运行在容器里(tomcat,resin XXXX),本地直接打开是执行不了的,我折腾了好久才弄懂这个问题的 注,chrome 通过注册表注册表 只能调用本地的 exe 或者bat文件,不能调用 ppt word 这样的问题,...

    java调用本地打印机

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

    jni本地调用4

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

    web调用本地程序示例

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

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

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

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

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

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

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

    js调用android本地方法的实现

    JS调用Android本地方法能够利用Web技术的灵活性和原生功能的强大性,为用户提供更好的体验。本篇文章将详细介绍如何在JS通过WebView调用Android的本地方法,同时规避`addJavascriptInterface`的安全问题。 首先,...

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

    3. **编写C代码并实现本地方法**: 根据生成的C头文件,你需要实现这些本地方法。例如,头文件可能包含如下内容: ```c JNIEXPORT jint JNICALL Java_test_testdll_get(JNIEnv *env, jclass clazz); JNIEXPORT ...

    java远程方法调用

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

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

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

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

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

Global site tag (gtag.js) - Google Analytics