猿问
下载APP

请问该怎么编写java native method?

怎么编写java native method


四季花海
浏览 84回答 4
4回答

慕森王

JDK源代码由C++、Java、C、汇编 这四种语言组成。JVM主体是C++写的,JNI部分是C,工具类是Java写的,JVM里混有汇编代码。路径:openjdk-7-fcs-src-b147\jdk\src\share\native\java\lang\System.c 找到这个/* Only register the performance-critical methods */static JNINativeMethod methods[] = {{"currentTimeMillis", "()J", (void *)&JVM_CurrentTimeMillis},{"nanoTime", "()J", (void *)&JVM_NanoTime},{"arraycopy", "(" OBJ "I" OBJ "II)V", (void *)&JVM_ArrayCopy},};方法的实现应该在JVM部分,路径openjdk-7-fcs-src-b147\hotspot\src\share,不同的操作系统实现不一样,应该是在对应的操作系统的包下

守着一只汪

什么是Native Method简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。"A native method is a Java method whose implementation is provided by non-java code."在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。,下面给了一个示例:public class IHaveNatives{native public void Native1( int x ) ;native static public long Native2() ;native synchronized private float Native3( Object o ) ;native void Native4( int[] ary ) throws Exception ;}这些方法的声明描述了一些非java代码在这些java代码里看起来像什么样子(view).标识符native可以与所有其它的java标识符连用,但是abstract除外。这是合理的,因为native暗示这些方法是有实现体的,只不过这些实现体是非java的,但是abstract却显然的指明这些方法无实现体。native与其它java标识符连用时,其意义同非Native Method并无差别,比如native static表明这个方法可以在不产生类的实例时直接调用,这非常方便,比如当你想用一个native method去调用一个C的类库时。上面的第三个方法用到了native synchronized,JVM在进入这个方法的实现体之前会执行同步锁机制(就像java的多线程。)一个native method方法可以返回任何java类型,包括非基本类型,而且同样可以进行异常控制。这些方法的实现体可以制一个异常并且将其抛出,这一点与java的方法非常相似。当一个native method接收到一些非基本类型时如Object或一个整型数组时,这个方法可以访问这非些基本型的内部,但是这将使这个native方法依赖于你所访问的java类的实现。有一点要牢牢记住:我们可以在一个native method的本地实现中访问所有的java特性,但是这要依赖于你所访问的java特性的实现,而且这样做远远不如在java语言中使用那些特性方便和容易。native method的存在并不会对其他类调用这些本地方法产生任何影响,实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。JVM将控制调用本地方法的所有细节。需要注意当我们将一个本地方法声明为final的情况。用java实现的方法体在被编译时可能会因为内联而产生效率上的提升。但是一个native final方法是否也能获得这样的好处却是值得怀疑的,但是这只是一个代码优化方面的问题,对功能实现没有影响。如果一个含有本地方法的类被继承,子类会继承这个本地方法并且可以用java语言重写这个方法(这个似乎看起来有些奇怪),同样的如果一个本地方法被fianl标识,它被继承后不能被重写。本地方法非常有用,因为它有效地扩充了jvm.事实上,我们所写的java代码已经用到了本地方法,在sun的java的并发(多线程)的机制实现中,许多与操作系统的接触点都用到了本地方法,这使得java程序能够超越java运行时的界限。有了本地方法,java程序可以做任何应用层次的任务

烙印99

通过jni接口调用native步骤如下:1.创建一个 android project, 名字叫Why2 在工程Why中添加一个Java类,class名为Jni。这个类是一个JNI接口的Java类,文件名为Jni.java。package com.yarin.android.Why;public class Jni {public native int getCInt();public native String getCString();}3.将工程Why下的 "src\com\yarin\android\Why" 目录下的Jni.java文件copy到“Why\bin\classes”下.4.Generate Jni.class file via the command below:javac jni.javaThen copy the Jni.class file generated to cover and replace the original Jni.class file in directory “Why\bin\classes\com\yarin\android\Why”.------The original Jni.class file, you must build the java project first to generate it.5.Generate c style header filejavah –classpath C:\android-ndk-r6b\myproject\Why\bin\classes com.yarin.android.Why.Jnicom.yarin.android.Why is my package name appeared in Jni.java file.com_yarin_android_Why_Jni.h is like below:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_yarin_android_Why_Jni */#ifndef _Included_com_yarin_android_Why_Jni#define _Included_com_yarin_android_Why_Jni#ifdef __cplusplusextern "C" {#endif/** Class: com_yarin_android_Why_Jni* Method: getCInt* Signature: ()I*/JNIEXPORT jint JNICALL Java_com_yarin_android_Why_Jni_getCInt(JNIEnv *env, jobject object); ---you need to supplement the parameter name yourself/** Class: com_yarin_android_Why_Jni* Method: getCString* Signature: ()Ljava/lang/String;*/JNIEXPORT jstring JNICALL Java_com_yarin_android_Why_Jni_getCString(JNIEnv *env, jobject object);#ifdef __cplusplus}#endif#endif6.Add com_yarin_android_Why_Jni.c file corresponding to the above c style header file, then add implemented code.#include <stdio.h>#include <stdlib.h>#include "com_yarin_android_Why_Jni.h"int add(){int x,y;x = 111;y = 22;x += y;return x;}JNIEXPORT jint JNICALL Java_com_yarin_android_Why_Jni_getCInt(JNIEnv *env, jobject object){return add();}JNIEXPORT jstring JNICALL Java_com_yarin_android_Why_Jni_getCString(JNIEnv *env, jobject object){(*env)->NewStringUTF(env, " Why is ok ^_^ ----->> ");}7.然后实现在工程Why下创建目录jni,并且copy com_yarin_android_Why_Jni.c /h 到jni目录下。8.在"Why\jni"目录下编写Android.mk ,在"android-ndk-r6b\jni"下编写Application.mk , 然后在NDK环境下编译native code,生成动态库libWhy.so。9.在java工程中加入调用native 动态库的代码:package com.yarin.android.Why;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;public class WhyActivity extends Activity {static{System.loadLibrary("Why");}/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Jni jni = new Jni();TextView view = new TextView(this);view.setText(jni.getCString() + Integer.toString(jni.getCInt()));setContentView(view);}}10 编译Why工程,然后 run as Android Application, 就能看到native code的调用结果了。Tip:Usage of the command javah.javah -d <outputdir> -classpath <classpath> <fully_qualified_class>where:'outputdir' is the directory where to put the generated header file'classpath' contains an absolute path to the directory containing your root package (as mentionned by Glen)'fully_qualified_class' is the name of the class containing native methods without .class extension-jni option is not required (set by default)

三国纷争

1.Power.java--> find corresponding native cfile(查找对应的具体用C实现的C文件) android.os.Power.java:native file ---->.../jni/android_os_Power.cpp2. in android_os_Power.c, you canfind: 点击(此处)折叠或打开static JNINativeMethod method_table[]=// Native functiontable { {"acquireWakeLock","(ILjava/lang/String;)V",(void*)acquireWakeLock}, {"releaseWakeLock","(Ljava/lang/String;)V",(void*)releaseWakeLock}, {"setLastUserActivityTimeout","(J)I",(void*)setLastUserActivityTimeout }, {"setScreenState","(Z)I",(void*)setScreenState }, {"shutdown","()V",(void*)android_os_Power_shutdown }, {"reboot","(Ljava/lang/String;)V",(void*)android_os_Power_reboot },}; int register_android_os_Power(JNIEnv *env)//functionto register mapping tablefrom name //tofunction{ returnAndroidRuntime::registerNativeMethods( env,"android/os/Power", method_table, NELEM(method_table));}3. in /framework/base/core/jni , a file named:AndroidRuntime.cpp 1) a global register function array 点击(此处)折叠或打开static const RegJNIRec gRegJNI[]= { // ... register_android_os_Power, } 2) Register native function process 点击(此处)折叠或打开int AndroidRuntime::startReg(JNIEnv* env)orJava_com_android_internal_util_WithFramework_registerNatives(...)orJava_LoadClass_registerNatives(....) ---> register_jni_procs(gRegJNI, NELEM(gRegJNI),env) ---> foreach(member of gRegJNI)call register_XXX_XXX_XXX..XXX() //so here register_android_os_power() will becalled ---> AndroidRuntime::registerNativeMethods(env, /*class_namelike */"android/os/Power", /*method table like*/method_table, size) ---> jniRegisterNativeMethods(env, className,gMethods, numMethods) ---> pEnv->RegisterNatives(env, clazz, gMethods,numMethods); ---> foreach(method) call dvmRegisterJNIMethod(ClassObject* clazz, const char*methodName, constchar* signature, void* fnPtr) ---> call dvmSetNativeFunc(method, dvmCallSynchronizedJNIMethod, fnPtr); //for sycn method or call dvmSetNativeFunc(method, dvmCallJNIMethod,fnPtr); --->((Method*)method)->insns = insns; //set actual codespace to be executed for a native function4.calling a native method ( JNI method) 点击(此处)折叠或打开void dvmPlatformInvoke(void* pEnv,ClassObject* clazz,int argInfo,int argc, const u4*argv,const char* shorty, void* func, JValue*pReturn) dvmCallMethod()/dvmInvokeMethod
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答