网络推广网站首页大图/百度提交网址多久才会收录
目录
版本信息:
写在前面:
源码论证:
总结:
版本信息:
jdk版本:jdk8u40
写在前面:
在Java类库中很多类都有一个registerNatives的native方法,并且写在static静态代码块中进行初始化调用,有不少的读者应该会对这个方法感兴趣,但是此方法是一个native方法,让不少的读者望而却步,所以笔者写在这一篇关于registerNatives方法的文章~
要真正弄懂registerNatives方法非常的复杂,因为你需要明白 C/C++ 的执行和动态链接库的原理、以及JVM对于动态链接库的封装处理、以及Java语言作为解释性语言JVM的解释器引擎如何对其做处理、以及JVM对于类加载的一个过程,他是如何链接native方法的~
这并不是在劝退各位读者,而是让读者有一个对知识的认知。当然,笔者认为高级的封装是有他的意义存在,屏蔽掉底层的各种复杂的实现。所以笔者也会尽量用通俗易懂的方式介绍registerNatives方法
源码论证:
首先需要说明白registerNatives这个native方法存在的意义:把类中其他native方法的实现映射到JVM虚拟机中内部的方法(native方法的实现是c/c++语言,而JVM也是c++语言实现,所以是完成一个其他native方法的映射)
在JVM的实现Hotspot源码中,一般情况下native层面的源码文件命名是跟类名一致,比如拿Thread.java 类来说,在Hotspot中他的native层面文件就是 Thread.c 。 正好Thread类中也有registerNatives,接下来我们就看到Thread中registerNatives方法的native层面源码实现
/src/share/native/java/lang/Thread.c 文件中
typedef struct {char *name;char *signature;void *fnPtr;
} JNINativeMethod;static JNINativeMethod methods[] = {{"start0", "()V", (void *)&JVM_StartThread},{"stop0", "(" OBJ ")V", (void *)&JVM_StopThread},{"isAlive", "()Z", (void *)&JVM_IsThreadAlive},{"suspend0", "()V", (void *)&JVM_SuspendThread},{"resume0", "()V", (void *)&JVM_ResumeThread},{"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority},{"yield", "()V", (void *)&JVM_Yield},{"sleep", "(J)V", (void *)&JVM_Sleep},{"currentThread", "()" THD, (void *)&JVM_CurrentThread},{"countStackFrames", "()I", (void *)&JVM_CountStackFrames},{"interrupt0", "()V", (void *)&JVM_Interrupt},{"isInterrupted", "(Z)Z", (void *)&JVM_IsInterrupted},{"holdsLock", "(" OBJ ")Z", (void *)&JVM_HoldsLock},{"getThreads", "()[" THD, (void *)&JVM_GetAllThreads},{"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads},{"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};
JNINativeMethod结构体定义了native方法的名字、签名、目标方法的地址。在Thread.c 文件中定义了JNINativeMethod结构体数组,完成了native方法名和目标方法映射,而这些方法名恰好是Thread.java 类中其他native方法,这也对应上上文说的 " 把类中其他native方法的实现映射到JVM虚拟机中内部的方法 " 等同于说执行Thread类中sleep方法就会执行JVM_Sleep这个JVM内部的方法
接下来我们看到registerNatives方法的实现,看它是如何完成的映射。
JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{// JNIEnv结构体是JNI给c语言提供访问JVM使用的,内部有很多函数去访问JVM// 而这里就是调用JNIEnv结构体中RegisterNatives方法(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
又开发过JNI的读者可能这里就很容易理解,JNIEnv这个结构体是JNI给c语言提供访问JVM使用的,JNIEnv结构体内部有很多函数去访问JVM,而这里就是调用JNIEnv结构体中RegisterNatives方法,所以我们看到 src/share/vm/prims/jni.cpp 文件中RegisterNatives方法。
JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,const JNINativeMethod *methods,jint nMethods))jint ret = 0;// 获取到Klass对象,在Hotspot中Klass对象可以理解是Java的类KlassHandle h_k(thread, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));// 遍历JNINativeMethod结构体数组for (int index = 0; index < nMethods; index++) {// 获取到方法名和签名const char* meth_name = methods[index].name;const char* meth_sig = methods[index].signature;int meth_name_len = (int)strlen(meth_name);// 把方法名和签名转换成Hotspot中符号信息(实际上这一步无需关心)TempNewSymbol name = SymbolTable::probe(meth_name, meth_name_len);TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));// 我们需要把目标方法注册到类中的native方法// 这一步就是完成注册bool res = register_native(h_k, name, signature,(address) methods[index].fnPtr, THREAD);}return ret;
JNI_END
- 获取到Klass对象,在Hotspot中Klass对象可以理解为Java的类,因为类中定义了方法,而这一步就是要把目标方法(JVM内部方法)注册到类中的native方法
- 遍历JNINativeMethod结构体数组
- 获取到方法名和签名信息,因为需要通过它们找到native方法
- 调用register_native方法完成注册工作
接下来只需要看到register_native方法的实现即可。
static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) {// 通过方法名和签名找到类中的方法Method* method = k()->lookup_method(name, signature);………… // 省略一些判断if (entry != NULL) {// 把目标方法(JVM内部方法)注册到类中的native中// 下次调用native方法时,执行的就是JVM内部的方法method->set_native_function(entry,Method::native_bind_event_is_interesting);}………… // 省略一些判断return true;
}
这里就特别的简单了,通过方法名和签名得到方法,然后把目标方法(JVM内部方法)设置到方法中,下次执行native方法时,就会执行JVM内部的方法~
总结:
整体流程不难,但是笔者是直接 " 告诉答案 " ,如果说需要完整的闭环JNI和native方法的注册和native方法的执行,这个过程将会特别的复杂,不过学习某个层面,就应该把他的下层当作黑盒来理解即可~
相关文章:

JVM源码剖析之registerNatives方法
目录 版本信息: 写在前面: 源码论证: 总结: 版本信息: jdk版本:jdk8u40 写在前面: 在Java类库中很多类都有一个registerNatives的native方法,并且写在static静态代码块中进行初…...

HarmonyOS鸿蒙应用开发——数据持久化Preferences
文章目录 数据持久化简述基本使用与封装测试用例参考 数据持久化简述 数据持久化就是将内存数据通过文件或者数据库的方式保存到设备中。HarmonyOS提供两两种持久化方案: Preferences:主要用于保存一些配置信息,是通过文本的形式存储的&…...

C++STL库的 deque、stack、queue、list、set/multiset、map/multimap
deque 容器 Vector 容器是单向开口的连续内存空间, deque 则是一种双向开口的连续线性空 间。所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,当然, vector 容器也可以在头尾两端插入元素,但是在其…...

Vuex快速上手
一、Vuex 概述 目标:明确Vuex是什么,应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具,状态就是数据。 大白话:Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如:购…...

计网 - LVS 是如何直接基于 IP 层进行负载平衡调度
文章目录 模型LVS的工作机制初探LVS的负载均衡机制初探 模型 大致来说,可以这么理解(只是帮助我们理解,实际上肯定会有点出入),对于我们的 PC 机来说,物理层可以看成网卡,数据链路层可以看成网卡…...

GEE机器学习——利用支持向量机SVM进行土地分类和精度评定
支持向量机方法 支持向量机(Support Vector Machine,SVM)是一种常用的机器学习算法,主要用于分类和回归问题。SVM的目标是找到一个最优的超平面,将不同类别的样本点分隔开来,使得两个类别的间隔最大化。具体来说,SVM通过寻找支持向量(即距离超平面最近的样本点),确定…...

【ARM Trace32(劳特巴赫) 使用介绍 13 -- Trace32 断点 Break 命令篇】
文章目录 1. Break.Set1.1 TRACE32 Break1.1.1 Break命令控制CPU的暂停1.2 Break.Set 设置断点1.2.1 Trace32 程序断点1.2.2 读写断点1.2.2.1 变量被改写为特定值触发halt1.2.2.2 设定非值触发halt1.2.2.4 变量被特定函数改写触发halt1.2.3 使用C/C++语法设置断点条件1.2.4 使用…...

【JVM入门到实战】(三) 查看字节码文件的工具
一、 javap -v命令 javap是JDK自带的反编译工具,可以通过控制台查看字节码文件的内容。适合在服务器上查看字节码文件内容。直接输入javap查看所有参数。输入javap -v 字节码文件名称 查看具体的字节码信息。(如果jar包需要先使用 jar –xvf 命令解压&a…...

9:00面试,9:05就出来了,问的问题有点变态。。。
从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到12月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40…...

无需重启,修改Linux服务器时区
Linux修改服务器时区(无需重启) 1、复制命令:2、使用tzselect命令:3、使用date查看是否修改正确 1、复制命令: cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime2、使用tzselect命令: tzselect按照要…...

【Android嵌入式开发及实训课程实验】【项目1】 图形界面——计算器项目
【项目1】 图形界面——计算器项目 需求分析界面设计实施1、创建项目2、 界面实现实现代码1.activity_main.xml2.Java代码 - MainActivity.java 3、运行测试 注意点结束~ 需求分析 开发一个简单的计算器项目,该程序只能进行加减乘除运算。要求界面美观,…...

利用SPSS进行神经网络分析过程及结果解读
模拟人类实际神经网络的数学方法问世以来,人们已慢慢习惯了把这种人工神经网络直接称为 神经网络。 神经网络在系统辨识、模式识别、智能控制等领域有着广泛而吸引人的前景,特别在智能控制中,人们对神经网络的自学习功能尤其感兴趣࿰…...

聚观早报 |东方甄选将上架文旅产品;IBM首台模块化量子计算机
【聚观365】12月6日消息 东方甄选将上架文旅产品 IBM首台模块化量子计算机 新思科技携手三星上新兴领域 英伟达与软银推动人工智能研发 苹果对Vision Pro供应商做出调整 东方甄选将上架文旅产品 东方甄选宣布12月10日将在东方甄选APP上线文旅产品,受这一消息影…...

web服务器之——www服务器的基本配置
目录 一、www简介 1、什么是www 2、www所用的协议 3、WEB服务器 4、主要数据 5、浏览器 二、 网址及HTTP简介 1、HTTP协议请求的工作流程 三、www服务器的类型(静态网站(HTML), 动态网站(jsp python,php,perl)) 1、 仅提供…...

微信小程序 -- ios 底部小黑条样式问题
问题: 如图,ios有的机型底部伪home键会显示在按钮之上,导致点击按钮的时候误触 解决: App.vue <script>export default {wx.getSystemInfo({success: res > {let bottomHeight res.screenHeight - res.safeArea.bott…...

白盒测试:探索软件内部结构的有效方法
引言: 在软件开发过程中,测试是确保软件质量的关键环节。传统的黑盒测试方法主要关注软件的功能和外部行为,而忽略了软件的内部结构和实现细节。然而,随着软件复杂性的增加,仅仅依靠黑盒测试已经无法满足项目的需求。因…...

图论-并查集
并查集(Union-find Sets)是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图,求最小生成树Kruskal算法和最近公共祖先(LCA)等. 并查集的基本操作主要有: .1.初始化 2.查询find 3.合并union 一般我们都会采用路径压缩 这样…...

redis-学习笔记(Jedis 通用命令)
flushAll 清空全部的数据库数据 jedis.flushAll();set & get set 命令 get 命令 运行结果展示 exists 判断该 key 值是否存在 当 redis 中存在该键值对时, 返回 true 如果键值对不存在, 返回 false keys 获取所有的 key 值 参数是模式匹配 *代表匹配任意个字符 _代表匹配一…...

C语言:高精度乘法
P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 第一次画图,略显简陋。 由图可以看出c的小标与x,y下标的关系为x的下标加上y的下标再减一。 由此得到: c [ i j - 1 ] x [ i ] * y [ j ]x #include<stdio.h> #include<st…...

UE4 Niagara学习笔记
需要在其他发射器的同一个粒子位置发射其他粒子就用Spawn Particles from other Emitter 把发射器名字填上去即可 这里Move to Nearest Distance Field Subface GPU,可以将生成的Niagara附着到最近的物体上 使用场景就是做的火苗附着到物体上...

多维时序 | Matlab实现GA-LSTM-Attention遗传算法优化长短期记忆神经网络融合注意力机制多变量时间序列预测
多维时序 | MATLAB实现BWO-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现BWO-CNN-BiGRU-Multihead-Attention多头注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | Matlab实…...

LeetCode205. Isomorphic Strings
文章目录 一、题目二、题解 一、题目 Given two strings s and t, determine if they are isomorphic. Two strings s and t are isomorphic if the characters in s can be replaced to get t. All occurrences of a character must be replaced with another character wh…...

Event Driven设计模式
EDA(Event-Driven Architecture)是一种实现组件之间松耦合、易扩展的架构方式。一个最简单的EDA设计需要包含如下几个组件: Events:需要被处理的数据。一个Event至少包含两个属性,类型和数据,类型决定了Eve…...

PostgreSql 设置自增字段
一、概述 序列类型是 PostgreSQL 特有的创建一个自增列的方法。包含 smallserial、serial和 bigserial 类型,它们不是真正的类型,只是为了创建唯一标识符列而存在的方便符号。其本质也是调用的序列,序列详情可参考:《PostgreSql 序…...

什么是泊松图像混合
泊松图像混合(Poisson Image Editing)的原理基于泊松方程。该方法旨在保持图像中的梯度一致性,从而在图像编辑中实现平滑和无缝的混合。以下是泊松图像混合的基本原理和公式: 泊松方程 泊松方程是一个偏微分方程,通常…...

OpenAI 承认 ChatGPT 最近确实变懒,承诺修复问题
文章目录 一. ChatGPT 指令遵循能力下降引发用户投诉1.1 用户抱怨回应速度慢、敷衍回答、拒绝回答和中断会话 二. OpenAI 官方确认 ChatGPT 存在问题,展开调查三. OpenAI 解释模型行为差异,回应用户质疑四. GPT-4 模型变更受人事动荡和延期影响 一. Chat…...

创作活动(四十九)———低代码:美味膳食或垃圾食品?
#低代码:美味膳食或垃圾食品?# 一、什么是低代码 低代码是一种开发方法,通过可视化界面和少量的编码,使开发者能够快速构建应用程序。它的目标是提高开发效率、降低开发成本,并支持快速迭代和敏捷开发。 二、低代码的…...

【DL-TensorFlow遇错】TensorFlow中遇错合集
TensorFlow中遇错合集 一、AttributeError: module tensorflow has no attribute placeholder二、RuntimeError: tf.placeholder() is not compatible with eager execution. 一、AttributeError: module tensorflow has no attribute placeholder 错误原因 tensorflow版本问…...

pymysql代替mysqlclient,解决mysqlclient因版本不兼容无法安装成功而无法连接mysql的问题
pymysql代替mysqlclient,解决mysqlclient因版本不兼容无法安装成功而无法连接mysql的问题 原因:版本或者环境兼容问题,导致如centos或者其他Linux无法安装mysqlclient模块 解决办法:安装pymysql作为替代 在Django中连接MySQL数…...

uni-app 设置当前page界面进入直接变为横屏模式
首先 我们打开项目的 manifest.json 在左侧导航栏中找到 源码视图 然后找到 app-plus 配置 在下面加上 "orientation": [//竖屏正方向"portrait-primary",//竖屏反方向"portrait-secondary",//横屏正方向"landscape-primary",//横屏…...