在博客java JNI (一)

虚拟机中classloader的JNILibrary 中讨论了java中的Library 是由classloader 来load的,那我们来看看 classloader是如何去load 一个library的。

ClassLoader.c

[cpp]

JNIEXPORT voidJNICALL

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, 0);if (cname == 0)return;

handle=JVM_LoadLibrary(cname);if(handle) {const char *onLoadSymbols[] =JNI_ONLOAD_SYMBOLS;

JNI_OnLoad_t JNI_OnLoad;inti;for (i = 0; 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);gotodone;

}if (!JVM_IsSupportedJNIVersion(jniVersion)) {char msg[256];

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);gotodone;

}

(*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);

}gotodone;

}

(*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);returnres;

}

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) returnJNI_TRUE;if (version == JNI_VERSION_1_4) returnJNI_TRUE;if (version == JNI_VERSION_1_6) returnJNI_TRUE;returnJNI_FALSE;

}

完整的加载过程就是

首先先加载动态链接库,尝试查找JNI_OnLoad方法,并且运行方法,对我们来说从而实现可以自定义的初始化方法。

java qt jni_java JNI 实现原理 (二) Linux 下如何 load JNILibrary相关推荐

  1. proc除了能用于oracle开发_能不能用于mysql开发_Oracle数据库开发(二).Linux下配置使用ProC...

    一.提要 上文简单介绍了Windows下ProC配置开发,这次我们使用Linux平台再次配置Oracle ProC开 发环境(RedHat Linux 9 + Oracle 92). <ORAC ...

  2. 【自学Docker容器二 ● Linux下Dokcer环境安装 】

    Docker自学系列 第一篇 [自学Docker容器一 ● 基础知识 ] 第二篇 [自学Docker容器二 ● Linux下Dokcer环境安装 ] 第三篇 [自学Docker容器三 ● Docker ...

  3. linux java 工具_Linux运维知识之linux下java版本管理工具jenv使用介绍

    本文主要向大家介绍了Linux运维知识之linux下java版本管理工具jenv使用介绍,通过具体的内容向大家展现,希望对大家学习Linux运维知识有所帮助. 不同的项目使用的java版本不同,每次切 ...

  4. linux java启动脚本文件_不错的linux下通用的java程序启动脚本

    #!/bin/sh #该脚本为Linux下启动java程序的通用脚本.即可以作为开机自启动service脚本被调用, #也可以作为启动java程序的独立脚本来使用. # #Author: tudaxi ...

  5. linux下java基于UDP编程聊天_基于Linux下的UDP编程

    一. Linux下UDP编程框架 使用UDP进行程序设计可以分为客户端和服务器端两部分. 1.服务器端程序包括: ? 建立套接字 ? 将套接字地址结构进行绑定 ? 读写数据 ? 关闭套接字 2.客户端 ...

  6. 缓冲区溢出漏洞原理及Linux下利用

    常见保护措施 ASLR ASLR 是一种防范内存损坏漏洞被利用的计算机安全技术.ASLR通过随机放置进程关键数据区域的地址空间来防止攻击者能可靠地跳转到内存的特定位置来利用函数,以防范恶意程序对已知地 ...

  7. php java bridge 安装_浅谈在linux下安装php-java-bridge

    本文介绍在linux下用源码安装Php/Java Bridge. 1.下载JavaBridge(http://sourceforge.net/projects/php-java-bridge/ ).由 ...

  8. linux跟踪内存检测原理,wooyun/Linux下基于内存分析的Rootkit检测方法.html at master · exitmsconfig/wooyun · GitHub...

    Linux下基于内存分析的Rootkit检测方法 - 路人甲 原文地址:http://drops.wooyun.org/tips/4731 0x00 引言 某Linux服务器发现异常现象如下图,确定被 ...

  9. Qt通过QStorageInfo获取磁盘大小,linux下可根据路径获取挂接磁盘的大小,而非获取所有磁盘大小的总和

    QStorageInfo类提供了系统当前挂载的存储和驱动器的相关信息,包括它们的空间,挂载点,标签名,文件系统名. 可以创建一个QStorageInfo对象,使用其静态方法mountedVolumes ...

最新文章

  1. 开发板运行linux下虚拟机ubuntu的ping
  2. 束文圣和黄立南Nature综述极端环境中的微生物多样性
  3. HAProxy高可用配置视频教程
  4. ARP的超时重新请求
  5. GTSAM Tutorial学习笔记
  6. 轮播插件swiper.js?
  7. Java黑皮书课后题第2章:2.15(几何:两点间距离)编写程序,提示用户输入两个点(x1,y1)和(x2,y2),显示两点距离
  8. python数据分析兼职能挣钱吗_Python开发能从事数据分析吗
  9. 中科院地平线开源state-of-the-art行人重识别算法EANet:增强跨域行人重识别中的部件对齐...
  10. PHP设计模式——解释器模式
  11. imu预积分_VINS 中的 IMU 预积分推导和代码解读
  12. JavaScript 上传文件并展示
  13. access 的几种更新语句:update where 与 update join where
  14. 啊哈C语言 第1章 编程改变思维(第0讲)
  15. NAT穿透技术、穿透原理和方法详解
  16. vue中组件根元素添加样式无效
  17. HDFS加密存储(HDP、Ranger、Ranger KMS实现)
  18. Julia1.4文档 —— 2. Julia的基本数值类型
  19. Linux系统Docker配置阿里云镜像加速器
  20. taylor+swift纽约公寓_欧美明星豪宅都有多美,眼见为实!

热门文章

  1. shell编程面试必会30题
  2. 【转】编程思想之消息机制
  3. 轻松得到C# ADO.NET的各种数据库连接字符串
  4. char,TCHAR,WCHAR区别
  5. IB客座主编(一)--安普布线亚太区业务总监黎启枝
  6. 打开 XP Pro SP2 远程桌面的多用户支持
  7. iview实现国际化
  8. jenkins内置变量的使用
  9. 拉格朗日乘子法学习[转载]
  10. 第一次做安卓项目使用的开源框架列表