http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html

Calling Java Methods

This section illustrates how you can call Java methods from native methods. Our example program, Callbacks.java, invokes a native method. The native method then makes a call back to a Java method. To make things a little more interesting, the Java method again (recursively) calls the native method. This process continues until the recursion is five levels deep, at which time the Java method returns without making any more calls to the native method. To help you see this, the Java method and the native method print a sequence of tracing information.

Calling a Java Method from Native Code

Let us focus on the implementation of Callbacks_nativeMethod, implemented in Callbacks.c. This native method contains a call back to the Java method Callbacks.callback.

JNIEXPORT void JNICALL
Java_Callbacks_nativeMethod(JNIEnv *env, jobject obj, jint depth)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V");
if (mid == 0)
return;
printf("In C, depth = %d, about to enter Java\n", depth);
(*env)->CallVoidMethod(env, obj, mid, depth);
printf("In C, depth = %d, back from Java\n", depth);
}

You can call an instance (non-static) method by following these three steps:

  • Your native method calls GetObjectClass. This returns the Java class object to which the Java object belongs.
  • Your native method then calls GetMethodID. This performs a lookup for the Java method in a given class. The lookup is based on the name of the method as well as the method signature. If the method does not exist, GetMethodID returns 0. An immediate return from the native method at that point causes aNoSuchMethodError to be thrown in Java code.
  • Lastly, your native method calls CallVoidMethod. This invokes an instance method that has void return type. You pass the object, method ID, and the actual arguments to CallVoidMethod.

Forming the Method Name and Method Signature

The JNI performs a symbolic lookup based on the method's name and type signature. This ensures that the same native method will work even after new methods have been added to the corresponding Java class.

The method name is the Java method name in UTF-8 form. Specify the method name for a constructor of a class by enclosing the word init within angle brackets (this appears as "<init>").

Note that the JNI uses method signatures to denote the type of Java methods. The signature (I)V, for example, denotes a Java method that takes one argument of type int and has return type void. The general form of a method signature argument is:

"(argument-types)return-type"

The following table summarizes the encoding for the Java type signatures:

Java VM Type Signatures
Signature Java Type
Z boolean
B byte
C char
S short
I int
J long
F float
D double
L fully-qualified-class ; fully-qualified-class
[ type type[]
( arg-types ) ret-type method type

For example, the Prompt.getLine method has the signature:

(Ljava/lang/String;)Ljava/lang/String;

whereas the Callbacks.main method has the signature:

([Ljava/lang/String;)V

Array types are indicated by a leading square bracket ([) followed by the type of the array elements.

Using javap to Generate Method Signatures

To eliminate the mistakes in deriving method signatures by hand, you can use the javap tool to print out method signatures. For example, by running:

javap -s -p Prompt

you can obtain the following output:

Compiled from Prompt.java
class Prompt extends java.lang.Object
/* ACC_SUPER bit set */
{
private native getLine (Ljava/lang/String;)Ljava/lang/String;
public static main ([Ljava/lang/String;)V
<init> ()V
static <clinit> ()V
}

The "-s" flag informs javap to output signatures rather than normal Java types. The "-p" flag causes private members to be included.

Calling Java Methods Using Method IDs

In JNI, you pass the method ID to the actual method invocation function. This makes it possible to first obtain the method ID, which is a relatively expensive operation, and then use the method ID many times at later points to invoke the same method.

It is important to keep in mind that a method ID is valid only as long as the class from which it is derived is not unloaded. Once the class is unloaded, the method ID becomes invalid. So if you want to cache the method ID, make sure to keep a live reference to the Java class from which the method ID is derived. As long as the reference to the Java class (the jclass value) exists, the native code keeps a live reference to the class. The section Local and Global References explains how to keep a live reference even after the native method returns and the jclass value goes out of scope.

Passing Arguments to Java Methods

The JNI provides several ways to pass arguments to a Java method. Most often, you pass the arguments following the method ID. There are also two variations of method invocation functions that take arguments in an alternative format. For example, the CallVoidMethodV function receives the arguments in a va_list, and theCallVoidMethodA function expects the arguments in an array of jvalue union types:

typedef union jvalue {
jboolean z;
jbyte b;
jchar c;
jshort s;
jint i;
jlong j;
jfloat f;
jdouble d;
jobject l;
} jvalue;

Besides CallVoidMethod function, the JNI also supports instance method invocation functions with other return types, such as CallBooleanMethodCallIntMethod, and so on. The return type of the method invocation function must match with the Java method you wish to invoke.

Calling Static Methods

You can call static Java method from your native code by following these steps:

  • Obtain the method ID using GetStaticMethodID, as opposed to GetMethodID.
  • Pass the class, method ID, and arguments to the family of static method invocation functions: CallStaticVoidMethodCallStaticBooleanMethod, and so on.

If you compare instance method invocation functions to static method invocation functions, you will notice that instance method invocation functions receive the object, rather than the class, as the second argument following the JNIEnv argument. For example, if we add a static method

   static int incDepth(int depth) {return depth + 1};

into Callback.java, we can call it from Java_Callback_nativeMethod using:

JNIEXPORT void JNICALL
Java_Callbacks_nativeMethod(JNIEnv *env, jobject obj, jint depth)
{
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "incDepth", "(I)I");
if (mid == 0)
return;
depth = (*env)->CallStaticIntMethod(env, cls, mid, depth);

Calling Instance Methods of a Superclass

You can call instance methods defined in a superclass that have been overridden in the class to which the object belongs. The JNI provides a set of CallNonvirtual<type>Method functions for this purpose. To call instance methods from the superclass that defined them, you do the following:

  • Obtain the method ID from the superclass using GetMethodID, as opposed to GetStaticMethodID).
  • Pass the object, superclass, method Id, and arguments to the family of nonvirtual invocation functions: CallNonvirtualVoidMethodCallNonvirtualBooleanMethod, and so on.

It is rare that you will need to invoke the instance methods of a superclass. This facility is similar to calling a superclass method, say f, using:

super.f();

in Java.

Calling a Java Method from Native Code的更多相关文章

  1. NDK(3)java.lang.UnsatisfiedLinkError: Native method not found解决方法

    调用native方法时报错如下 : “java.lang.UnsatisfiedLinkError: Native method not found....  ”: 原因分析: 链接器只看到了在so中 ...

  2. java.lang.UnsatisfiedLinkError: Native method not found 三种可能解决方案

    so文件编译生成后,运行时,有时候会遇到java.lang.UnsatisfiedLinkError: Native method not found问题,有可能是以下三种因素: 一.Jni方法头部大 ...

  3. 修改Android 4.2.2的原生Camera引出的java.lang.UnsatisfiedLinkError: Native method not found,及解决方法

    修改Android 4.2.2的原生Camera应用,做一些定制,将Camera的包名从之前的 package com.android.* 修改成了com.zhao3546.*. 调整后,应用可以正常 ...

  4. [Xamarin] 透過Native Code呼叫 JavaScript function (转帖)

    今天我們來聊聊關於如何使用WebView 中的Javascript 來呼叫 Native Code 的部分 首先,你得先來看看這篇[Xamarin] 使用Webview 來做APP因為這篇文章至少講解 ...

  5. NDK开发历程(一):android native code的调试方法

    引用:http://www.cnblogs.com/ychellboy/archive/2013/02/22/2922683.html 使用NDK在android上做开发是一件“痛并快乐着”的差事,之 ...

  6. java基础-关键字-native

     一. 什么是Native Method    简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个java的方法:该方法的实现由 ...

  7. java中的native方法和修饰符(转)

    Java中的native修饰符 今天偶然看代码,发现别人有这样写的方法,并且jar里面有几个dll文件,比较奇怪,于是把代码打开,发现如下写法. public native String GSMMod ...

  8. Java中的native方法

    博客引用地址:Java中的native方法 今天花了两个小时把一份关于什么是Native Method的英文文章好好了读了一遍,以下是我依据原文的理解. 一. 什么是Native Method 简单地 ...

  9. Java中的native关键字与JNI

    一.先说一下大致的意思: jdk提供的类库源代码中有一些方法没有实现,这些方法前有native关键字,如object类中的 : native Object clone() throws CloneNo ...

随机推荐

  1. linux中chown命令

    chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名或者组ID:文件是以空格分开的要改变权限的文件列表,支持通配符.系统管理员经常使用chown命令,在将文件拷贝 ...

  2. UISegmentedControl: 增加代理方法

    UISegmentedControl 没有代理方法可以设置,不能在选择之前做预处理.为此,重写了 UISegmentedControl 创建文件 RFSegmentedControl,继承自 UISe ...

  3. Thinkphp5笔记四:设置模板路径

    默认的模板路径在模块/view文件里面.如果你觉得这样不太方便管理,想要把他设置Template目录下,可以这样做. 模板参数 ,能够影响的它参数,是当前模块下config.php template- ...

  4. django时区设置(timezone)

    django时区设置(timezone): 默认: TIMEZONE:'America/Chicago'(以前的版本,现在的版本默认的都是UTC时间.) Chicago时间,为UTC/GMT -6 小 ...

  5. Python爬虫-什么是爬虫?

    百度百科是这样定义爬虫的: 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂 ...

  6. srv.exe蠕虫病毒~

    你是否在电脑使用过程中遇到过这样的问题: 1.文件运行后,同目录下会出现一个原名 srv.exe的文件 2.文件运行后会把浏览器打开 3.电脑上的html文件末尾会增加一大堆东西 完了,电脑中了srv ...

  7. .NET工具集合

    工具 (1) 代码分析 .NET Memory Profiler - http://memprofiler.com/ANTS Profiler - http://www.red-gate.com/co ...

  8. Linq To EF (添加记录后获取添加的自增ID和叫“ID”的列不是自增列不让插入的问题)

    1:添加记录后,如何获取新添加的ID的值 比如,一个实体 TestEntity   对应一个表TestEntity(ID主键自增,Name,age),使用linq to ef   添加一条记录后,如何 ...

  9. 一致性Hash算法原理及C#代码实现

    一.一致性Hash算法原理 基本概念 一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希空间环如下: 整个空间按顺 ...

  10. 5 -- Hibernate的基本用法 --2 Hibernate入门

    5.2.1 Hibernate 下载和安装 5.2.2 Hibernate 的数据库操作 5.2.3 在Eclipse中使用Hibernate 啦啦啦