java JNI 实现原理 (二) Linux 下如何 load JNILibrary
ClassLoader.c
[cpp]
JNIEXPORT void JNICALL
Java_java_lang_ClassLoader_00024NativeLibrary_load
(JNIEnv *env, jobject this, jstring name)
{
const char *cname;
jint jniVersion;
jthrowable cause;
void * handle; if (!initIDs(env))
return; cname = JNU_GetStringPlatformChars(env, name, );
if (cname == )
return;
handle = JVM_LoadLibrary(cname);
if (handle) {
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
JNI_OnLoad_t JNI_OnLoad;
int i;
for (i = ; i < sizeof(onLoadSymbols) / sizeof(char *); i++) {
JNI_OnLoad = (JNI_OnLoad_t)
JVM_FindLibraryEntry(handle, onLoadSymbols[i]);
if (JNI_OnLoad) {
break;
}
}
if (JNI_OnLoad) {
JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm);
jniVersion = (*JNI_OnLoad)(jvm, NULL);
} else {
jniVersion = 0x00010001;
} cause = (*env)->ExceptionOccurred(env);
if (cause) {
(*env)->ExceptionClear(env);
(*env)->Throw(env, cause);
JVM_UnloadLibrary(handle);
goto done;
} if (!JVM_IsSupportedJNIVersion(jniVersion)) {
char msg[];
jio_snprintf(msg, sizeof(msg),
"unsupported JNI version 0x%08X required by %s",
jniVersion, cname);
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
JVM_UnloadLibrary(handle);
goto done;
}
(*env)->SetIntField(env, this, jniVersionID, jniVersion);
} else {
cause = (*env)->ExceptionOccurred(env);
if (cause) {
(*env)->ExceptionClear(env);
(*env)->SetLongField(env, this, handleID, (jlong)NULL);
(*env)->Throw(env, cause);
}
goto done;
}
(*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle)); done:
JNU_ReleaseStringPlatformChars(env, name, cname);
}
1. JVM_LoadLibrary
jvm中load library 核心函数,实现也非常简单,在linux下调用了系统函数dlopen去打开库文件,详细可参考方法
[cpp]
void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
2. JVM_FindLibraryEntry
JVM在加载库文件时候,会去尝试查找库中的JNI_ONLOAD方法的地址,而在Linux中调用了dlsym函数通过前面的dlopen加载库的指针去获取方法的地址,而dlsym在glibc2.0是非线程安全的,需要锁的保护,虽然在java中加载库已经有锁的保护,但只是针对同一个classloader对象的细粒度锁。
[cpp]
void* os::dll_lookup(void* handle, const char* name) {
pthread_mutex_lock(&dl_mutex);
void* res = dlsym(handle, name);
pthread_mutex_unlock(&dl_mutex);
return res;
}
3. 方法JNI_OnLoad
JVM提供了一种方式允许你在加载库文件的时候做一些你想做的事情,也就是JNI_OnLoad方法
在2中提到过在加载动态链接库,JVM会去尝试查找JNI_OnLoad方法,同时也会调用该函数,这样你个人可以在函数里做一些初始化的事情,比如register native方法。
[cpp]
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{}
JNI_OnLoad中返回的是JNI 的version,在1.6版本的情况下支持如下
[cpp]
jboolean Threads::is_supported_jni_version(jint version) {
if (version == JNI_VERSION_1_2) return JNI_TRUE;
if (version == JNI_VERSION_1_4) return JNI_TRUE;
if (version == JNI_VERSION_1_6) return JNI_TRUE;
return JNI_FALSE;
}
完整的加载过程就是
首先先加载动态链接库,尝试查找JNI_OnLoad方法,并且运行方法,对我们来说从而实现可以自定义的初始化方法。
java JNI 实现原理 (二) Linux 下如何 load JNILibrary的更多相关文章
- DHCP原理与LINUX下的配置
DHCP原理与LINUX下的配置 目录 DHCP原理与LINUX下的配置 一.DHCP工作原理 1.DHCP概述 2.DHCP的优势 3.DHCP的分配方式 (1)自动分配 (2)手动分配 (3)动态 ...
- 一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse)
一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse) 给centOS安装图形界面 GNOME桌面环境 https://blog.csdn.net/wh211212/artic ...
- MongoDB和Java(1):Linux下的MongoDB安装
最近花了一些时间学习了下MongoDB数据库,感觉还是比较全面系统的,涉及了软件安装.客户端操作.安全认证.副本集和分布式集群搭建,以及使用Spring Data连接MongoDB进行数据操作,收获很 ...
- Linux下安装load generator步骤及问题解决
Linux下安装load generator步骤及问题解决 上一篇 / 下一篇 2014-08-06 18:33:00 / 个人分类:loadrunner相关 查看( 146 ) / 评论( 0 ) ...
- Redis(二)linux下redis安装
上篇讲解了redis在windows下的安装,接下来看看在linux下如何安装redis(纯菜鸟入门级别)? (1)redis的下载及编译 这里,首先进入存放文件目录(我的云服务器的是:cd /jel ...
- LINUX下CPU Load Average的一点研究
背景: 公司的某个系统工作在基于Linux的Cent OS下,一个host下同时连接了许多client, 最近某台Host总是显示CPU Load Average过高,我们单纯的以为是CPU的占用过高 ...
- 实验二 Linux下C语言编程基础
1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理 ...
- Nginx学习系列二Linux下Nginx实现负载均衡
关于在本地虚拟机(VMware 14)下安装Linux同时安装Nginx,请参考Nginx学习系列之搭建环境 1.启动Nginx 在Nginx安装成功的前提下,启动Nginx 已root模式登陆(权限 ...
- [笔记]MongoDB 二(Linux下MongoDB API C++编程)
一.连接类 DBClientConnection,派生自DBClientBase.DBClientBase类是实现query, update, insert, remove等功能. 构造函数:DBCl ...
随机推荐
- Dede文章标题长度修改
方法一.首先你要进入dedecms后台,系统——系统基本参数——其他选项——文档标题最大长度——在这修改为200或更大(其实200应该是足够了). 方法二.进入phpmyadmin,点击dede_ar ...
- matlab画图标题自定义字体大小
title('标题','fontname','Times New Roman','Color','b','FontSize',20);字体是Times New Roman,颜色是蓝色('b'即blue ...
- POJ-1321.棋盘问题.(回溯)
做完题之后看了网上的一些题解但是发现他们的解释大部分都是错误的,所以就自己写了一下,笔者能力也有限,有错误之处大家多多指正. 第一次看题的时候以为就是简单的八皇后,但是写了之后发现存在很多问题,比如需 ...
- Ionic后退刷新
版本:Angular 1.5.3.Ionic1.3.2 一 禁用缓存,全页面刷新. 每次前进/ 后退时,控制器都会执行. 1 AngularJS ui-router路由禁用缓存 var app = a ...
- c#引用命名空间的作用
System 包含用于定义常用值和引用数据类型.事件和事件处理程序.接口.属性和处理异常的基础类和基类.其他类提供支持下列操作的服务:数据类型转换,方法参数操作,数学计算,远程和本地程序调用,应用程序 ...
- UML 图C#
继承关系(类1继承类2) 代码: class Class1:Class2 { } class Class2 { } 实现(实现接口) 代码: interface interface1 { void s ...
- CSS学习总结2:CSS框模型
1.CSS框模型概述 CSS框模型规定了元素框处理元素内容.内边框.边框和外边框的方式. 元素框的最内部分是实际的内容,直接包围内容的是内边距.内边距呈现了元素的背景.内边距的边缘是边框.边框以外是外 ...
- C++中 左值和右值的区别
总结: C++11中所有的值属于左值,右值两者之一. 左值引用:指的是可以放在赋值表达式左边的事物——在堆上或者栈上分配的命名对象或者其他对象成员——有明确的内存地址. 对左值的const引用创建临时 ...
- 开源防火墙(pfSense)的安装部署与配置
pfSense是一个基于FreeBSD架构的软件防火墙,通常会被安装在多网卡的主板上作为路由器或者防火墙去使用.往往这些硬件都比较廉价,高性能的配置也就1千元左右.pfSense具有商业防火墙的大部分 ...
- iOS.WWDC
1. ASCIIwwdc: Searchable full-text transcripts of WWDC sessions http://asciiwwdc.com