Version Information(版本信息)

GetVersion

jint GetVersion(JNIEnv *env);

返回本地方法接口的版本。

PARAMETERS(参数):
env:JNI接口指针。

RETURNS(返回值):
返回高16位的主版本号和低16位的次版本号。

在JDK/JRE 1.1中,GetVersion()返回0x00010001。

在JDK/JRE 1.2中,GetVersion()返回0x00010002。

在JDK/JRE 1.4中,GetVersion()返回0x00010004。

在JDK/JRE 1.6中,GetVersion()返回0x00010006。

常量
SINCE JDK/JRE 1.2:

#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002/* Error codes */
#define JNI_EDETACHED    (-2)              /* thread detached from the VM */
#define JNI_EVERSION     (-3)              /* JNI version error 

SINCE JDK/JRE 1.4:

 #define JNI_VERSION_1_4 0x00010004

SINCE JDK/JRE 1.6:

#define JNI_VERSION_1_6 0x00010006

代码实现:

VersionInformation.cpp

extern "C"
JNIEXPORT jint JNICALL
Java_com_anniljing_jnidemo_VersionInformation_VersionInformation_getVersionInformation(JNIEnv *env,jclass clazz) {return env->GetVersion();
}

VersionInformation.java

public class VersionInformation {public static native int getVersionInformation();
}

MainActivity.java

  public void toVersionInformation(View view) {int versionInformation = VersionInformation.getVersionInformation();Log.d(TAG, "VersionInformation:0x" + Integer.toHexString(versionInformation));}

运行结果:

Class Operations(类操作)

DefineClass

jclass DefineClass(JNIEnv *env, const char *name, jobject loader,const jbyte *buf, jsize bufLen);

Loads a class from a buffer of raw class data. The buffer containing the raw class data is not referenced by the VM after the DefineClass call returns, and it may be discarded if desired.

从原始类数据的缓冲区加载一个类。 在 DefineClass 调用返回后,VM 不会引用包含原始类数据的缓冲区,如果需要,它可能会被丢弃。
PARAMETERS(参数):
env: the JNI interface pointer.
JNI接口指针

name: the name of the class or interface to be defined. The string is encoded in modified UTF-8.
要定义的类或接口的名称,该字符串使用修改后的UTF-8编码

loader: a class loader assigned to the defined class.
分配给已定义类的类加载器

buf: buffer containing the .class file data.
包含.class文件数据的缓冲区

bufLen: buffer length.
缓冲区长度

RETURNS(返回值):
Returns a Java class object or NULL if an error occurs.
返回java类对象,或者出现错误的时候返回NULL

THROWS(异常):
ClassFormatError: if the class data does not specify a valid class.
类格式化错误:如果不是有效的类,则抛出该错误

ClassCircularityError: if a class or interface would be its own superclass or superinterface.
类循环错误:如果该类或者接口的父类或者父接口为自己本身,则会抛出该错误

OutOfMemoryError: if the system runs out of memory.
内存溢出错误:如果系统运行出现内存溢出,则会抛出该错误

SecurityException: if the caller attempts to define a class in the “java” package tree.
安全异常:如果调用者企图在"java"源码包下定义一个类,则会抛出该异常

FindClass

jclass FindClass(JNIEnv *env, const char *name);

In JDK release 1.1, this function loads a locally-defined class. It searches the directories and zip files specified by the CLASSPATH environment variable for the class with the specified name.
在JDK1.1,该方法用来加载本地定义的类。它会从CLASSPATH环境变量指向的文件夹和zip文件

Since Java 2 SDK release 1.2, the Java security model allows non-system classes to load and call native methods. FindClass locates the class loader associated with the current native method; that is, the class loader of the class that declared the native method. If the native method belongs to a system class, no class loader will be involved. Otherwise, the proper class loader will be invoked to load and link the named class.
从JDK 1.2发行版之后,Java安全模型允许非本地系统类也可以加载和调用native方法(native methods)。FindClass 函数会加载与当前native方法关联的类加载器(class loader), 也就是定义了native方法的类的类加载器(class loader)。如果该native方法属于系统类(system class),则没有ClassLoader会被调用。否则,将使用正确的ClassLoader来加载(load)和链接(link)指定名称的类。

PS:我们需要重点理解这句话(FindClass locates the class loader associated with the current native method; that is, the class loader of the class that declared the native method)
1、FindClass locates the class loader
FindClass是加载类加载器的
2、associated with the current native method
与当前native方法相关联的
3、that is,the class loader of the class that declared the native method
也就是定义了native方法的类的类加载器

Since Java 2 SDK release 1.2, when FindClass is called through the Invocation Interface, there is no current native method or its associated class loader. In that case, the result of ClassLoader.getSystemClassLoader is used. This is the class loader the virtual machine creates for applications, and is able to locate classes listed in the java.class.path property.
从JDK 1.2发行版之后,当通过 Invocation 接口来调用 FindClass 函数,将没有当前的本地方法或与之关联的ClassLoader。这种情况下,会使用 ClassLoader.getSystemClassLoader 来替代。这个ClassLoader 是虚拟机用来创建应用(applications)的,它有能力定位到 java.class.path 参数下的所有类。

PARAMETERS(参数):
env: the JNI interface pointer.
JNI接口指针

name: a fully-qualified class name (that is, a package name, delimited by “/”, followed by the class name). If the name begins with “[“ (the array signature character), it returns an array class. The string is encoded in modified UTF-8
全称的类名(包名以 / 作为分隔符, 然后紧跟着类名),如果名字以 [开头(数组签名标识符),则返回一个数组的类,这个字符串也是MUTF-8

RETURNS(返回值):
Returns a class object from a fully-qualified name, or NULL if the class cannot be found.
指定名称的类的对象(a class object),或者没有找到对应的类时则返回 NULL

THROWS(异常):
ClassFormatError: if the class data does not specify a valid class.
类格式化错误:如果不是有效的类,则抛出该错误

ClassCircularityError: if a class or interface would be its own superclass or superinterface.
类循环错误:如果该类或者接口的父类或者父接口为自己本身,则会抛出该错误

OutOfMemoryError: if the system runs out of memory.
内存溢出错误:如果系统运行出现内存溢出,则会抛出该错误

SecurityException: if the caller attempts to define a class in the “java” package tree.
安全异常:如果调用者企图在"java"源码包下定义一个类,则会抛出该异常

代码实现

1、动态注册native方法时

JniDynamicLoad.java

public class JniDynamicLoad {public native int sum(int x, int y);public native String getNativeString();
}

jniDynamicLoadNative.cpp

//动态注册本地方法,需要c/c++中定义与native方法映射的方法
#include <jni.h>
#include <AndroidLog.h>#define JAVA_CLASS "com/anniljing/jnidemo/JniDynamicLoad"jint sum(JNIEnv *env, jobject jobj, int x, int y) {return x + y;
}jstring getMessage(JNIEnv *env, jobject jobj) {return env->NewStringUTF("This is from native string");
}static JNINativeMethod gMethods[] = {{"sum",             "(II)I",                (void *) sum},{"getNativeString", "()Ljava/lang/String;", (void *) getMessage}
};int registerNativeMethods(JNIEnv *env, const char *name, const JNINativeMethod *methods,jint nMethods) {jclass jcls;jcls = env->FindClass(name);if (jcls == nullptr) {return JNI_FALSE;}if (env->RegisterNatives(jcls, methods, nMethods) < 0) {return JNI_FALSE;}return JNI_TRUE;
}#define NELEM(x) ((int)(sizeof(x)/sizeof((x)[0])))JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {JNIEnv *env;if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {return JNI_FALSE;}registerNativeMethods(env, JAVA_CLASS, gMethods, NELEM(gMethods));LOGD("Dynamic load success");return JNI_VERSION_1_6;
}

MainActivity

public void findClass(View view) {JniDynamicLoad dynamicLoad = new JniDynamicLoad();Log.d(TAG, dynamicLoad.getNativeString());}


2、创建java普通对象时
JavaClass.java

package com.anniljing.jnidemo;import android.util.Log;public class JavaClass {public static String name;private String version;private static int sCode;public JavaClass() {Log.d("MainActivity","Init JavaClass");}public String getVersion() {return version;}public void setVersion(String version) {this.version = version;}public static void setCode(int code){sCode=code;}@Overridepublic String toString() {return "JavaClass{" +"version='" + version + '\''+"Code="+sCode+'\'' +'}';}
}

JniOperatorJavaClass.java

package com.anniljing.jnidemo.JavaClassOperator;import com.anniljing.jnidemo.JavaClass;public class JniOperatorJavaClass {public static native JavaClass operatorJavaClass();
}

JavaClassOperator.cpp

extern "C"
JNIEXPORT jobject JNICALL
Java_com_anniljing_jnidemo_JavaClassOperator_JniOperatorJavaClass_operatorJavaClass(JNIEnv *env,jclass clazz) {jclass jc=env->FindClass("com/anniljing/jnidemo/JavaClass");//调用java类的构造方法jmethodID construct=env->GetMethodID(jc,"<init>", "()V");jobject  javaClassObg=env->NewObject(jc,construct);return javaClassObg;
}



PS:如遇到这样的提示,不用理会,继续码代码,能正常运行的

参考官方文档地址
代码已同步GitHub

深入理解JNINativeInterface函数<一>相关推荐

  1. 深入理解javascript函数系列第二篇——函数参数

    前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数.本文是深入理解javascript函数 ...

  2. C++深入理解虚函数

    c++深入理解虚函数 虚函数的使用方法: (1)在基类用virtual声明成员函数为虚函数.这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便被调用. 在类外定义虚函数时,不必在定义vir ...

  3. 【Python】深入理解Python函数的9个黄金法则

    编程离不开函数.Python的函数除了具备传统意义上的函数特征外,又被赋予了其他一些特性,让它更灵活.更强大.这篇文章结合之前我推荐的一本Python宝书,又添加一些我的实践和理解,总结了深入理解Py ...

  4. python函数可以作为容器对象吗_正确理解Python函数是第一类对象

    正确理解 Python函数,能够帮助我们更好地理解 Python 装饰器.匿名函数(lambda).函数式编程等高阶技术. 函数(Function)作为程序语言中不可或缺的一部分,太稀松平常了.但函数 ...

  5. 正确理解Python函数是第一类对象

    正确理解 Python函数,能够帮助我们更好地理解 Python 装饰器.匿名函数(lambda).函数式编程等高阶技术. 函数(Function)作为程序语言中不可或缺的一部分,太稀松平常了.但函数 ...

  6. 用实际例子理解回调函数(Calback)

    用实际例子理解回调函数(Calback) 在我们编码的过程中,调用和回调几乎无处不在,但是我对回调函数到底是怎样一回事并没有一个真正透彻的理解,最近我查找学习了一些资料,学到了很多. 我参考了一些知乎 ...

  7. 【C语言】函数的理解——关于函数的声明

    函数的理解--关于函数的声明 #include <stdio.h> //void sumx(int begin,int end);//函数的声明 void sumx(int ,int ) ...

  8. 阅读并理解lv_demo_widgets()函数

    阅读并理解lv_demo_widgets()函数 现在我就是一个小白,我们用左键点进去这个函数lv_demo_widgets(),在LVGL.Simulator.cpp文件107行中.当前任务就是理解 ...

  9. 两分钟快速理解成本函数(cost function)

    对成本函数(cost function)的理解 成本函数是用以衡量假设函数h(x)准确性的工具. 直接上公式, 是不是有种熟悉感,最小二乘法,没错,对比理解一下就好了.该函数也被称为"平方误 ...

  10. 2020-08-14 理解 javascript 函数中的 curry

    理解 javascript 函数中的 curry 函数柯里化: 所谓函数柯里化就是把一个函数的多个传参变成多个函数的单个传参. 函数的柯里化,是 Javascript 中函数式编程的一个重要概念.它返 ...

最新文章

  1. 校准曲线(calibration curve)是什么?如何绘制校准曲线(calibration curve)?如何通过过校准曲线进行分析?什么是高估?什么是低估?
  2. Oracle RAC 启动与关闭 (rac 命令示例)
  3. 致NLP学习者,该跟大佬学习做项目了,附资料
  4. Java之品优购课程讲义_day05(8)
  5. java 货币格式 转换_java 货币 转换
  6. Python字符串format_map()
  7. 羽毛球 中的 切球 与 旋球
  8. 「干货」模拟信号和数字信号的差异
  9. 时间序列分类实践介绍(使用Python代码)
  10. 【BZOJ1491】[NOI2007]社交网络 Floyd
  11. php choose handler,Guzzle 源码分析
  12. 数学与物理桥梁下的鸟瞰
  13. think php 导出excel,Thinkphp5导出excel
  14. 大学计算机基础b上机考试题目,大学计算机基础上机考试题库
  15. FCES2019 panel5:北大、南大、浙大的人工智能课程是如何建设的?
  16. jmeter断言操作详解
  17. 韩信点兵C语言实现的几种方法
  18. 电脑蓝屏错误代码大全及解决办法
  19. SQL Server左连接
  20. 读书笔记——事务总结

热门文章

  1. 串口服务器远程距离,基于串口服务器的变频器远程控制系统.pdf
  2. 域名由谁管理?申请域名注册服务机构要具备什么条件?
  3. 杰里之2M 包加入来电铃声和来电报号的问题【篇】
  4. 计算机数据网络延迟,影响网络速度的两个重要因素:网络带宽和网络延迟!
  5. Error response from daemon: Container XXX is restarting, wait until the container is running
  6. Android-Glide清除缓存图片
  7. Error: not authorized on admin to execute command
  8. openwrt reboot流程
  9. MySQL第41题怎么评分_MySQL试题-测试、复习、查看
  10. Windows邮件添加QQ邮箱