1.调用JNI的时候,通常我们使用System.loadLibrary(String libname)来load JNI library, 同样也可以使用System.load(String fileName)来load JNI library,两者的区别是一个只需要设置库的名字,比如如果libA.so 只要输入A就可以了,而libA.so的位置可以同过设置 java.library.path 或者 sun.boot.library.path,后者输入的是完整路经的文件名。而不论用什么方法,最后JNI 库是通过classloader 来加载的

例:

(1)System.load 参数为库文件的绝对路径,可以是任意路径。

Java代码

(2)System.loadLibrary 参数为库文件名,不包含库文件的扩展名

注意:这种方式,加载的dll文件须是在java.library.path这一jvm变量所指向的路径中。 
可以通过如下方法来获得该变量的值:

Linux一般默认的java.library.path在/usr/lib下。

也可以自己通过VM参数-Djava.library.path=/usr/lib来显式的指定;或者通过增加环境变量export LD_LIBRARY_PATH=~/JavaNativeTest:$LD_LIBRARY_PATH

2.对于System.loadLibrary("NativeAgent");

在Linux下,动态库输出的文件名要是libNativeAgent.so

也就是说,如果System.loadLibrary("XXX");那么,在导出动态库时,动态库的名字就要是libXXX。否则,会报错:

3.每个classloader 对象都有自己的nativeLibrary 数组,一个全局的systemNativeLibrary 数组,一个全局的已经加载过的loadLibraryNames数组,和一个正在加载过程中的记录栈nativeLibraryContext

对同一个classloader 对象可以重复加载相同的库,对不同的classloader只可以加载一次相同的库

(1). 这里定义的相同的库是指相同路经下的同一个文件

(2).  这里同样指出的是同一个classloader对象,而不是同一种classloader类型,比如说如果一种classloader类型初始化成2个classloader对象,那么这两个对象就不能重复加载相同的库。

(3). 重复加载,并不代表真的重复加载,而是代码中保护

4.报错处理:ava.lang.UnsatisfiedLinkError: Native Library kjdbc_jni already loaded in another classloader

原因:

1.java虚拟机不允许一个JNI本地库同时被两个不同的classloader加载。

2.web服务器自动重启机制

当tomcat重启web应用时会自动加载dll, 但是重启web应用并不是重启整个tomcat,上一次启动的jvm仍然存在(jvm依然认为dll已经被之前的classloader加载过了),就不允许重启后web应用的classloader再去加载它。

但是手动重启tomcat,会将上一次启动的jvm关闭并重新启动,这样就可以正常加载。

解决思路:

虽然不同的web应用使用不同的classloader,但是所有web应用classloader的父classloader是同一个(BootstrapClassLoader)

启动类加载器BootstrapClassLoader:是嵌在JVM内核中的加载器,该加载器是用C++语言写的,主要负载加载JAVA_HOME/lib下的类库,启动类加载器无法被应用程序直接使用。

根据双亲委托模型,只要让父classloader加载jni本地库就可避免被多个classloader加载

具体做法:

将加载dll的代码抽出来,单独放到放到一个类里,写到一个static代码块,(加载这个类时就会先运行static代码块),然后将这个类变成一个jar文件,放到tomcat\lib文件夹下。再在web.xml中加一个监听,在项目启动的时候就加载这个类,加载dll.

JAVA 关于JNI本地库加载的更多相关文章

  1. 你知道 Java 类是如何被加载的吗?

    前言 最近给一个非 Java 方向的朋友讲了下双亲委派模型,朋友让我写篇文章深度研究下JVM 的 ClassLoader,我确实也好久没写 JVM 相关的文章了,有点手痒痒,涂了皮炎平也抑制不住的那种 ...

  2. java调用phantomjs采集ajax加载生成的网页

    java调用phantomjs采集ajax加载生成的网页 日前有采集需求,当我把所有的对应页面的链接都拿到手,准备开始根据链接去采集(写爬虫爬取)对应的终端页的时候,发觉用程序获取到的数据根本没有对应 ...

  3. java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  4. 深入java虚拟机学习 -- 类的加载机制(续)

    昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解. 这里我先把昨天的两份代码贴过来,重新看下: ...

  5. 深入java虚拟机学习 -- 类的加载机制(三)

    类的初始化时机 在上篇文章中讲到了类的六种主动使用方式,反射是其中的一种(Class.forName("com.jack.test")),这里需要注意一点:当调用ClasLoade ...

  6. 【java虚拟机系列】java中类与对象的加载顺序

    首先了解一下Java虚拟机初始化的原理. JVM通过加装.连接和初始化一个Java类型,使该类型可以被正在运行的Java程序所使用.类型的生命周期如下图所示: 装载和连接必须在初始化之前就要完成. 类 ...

  7. 【译】12. Java反射——类的动态加载和重新加载

    原文地址:http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html 博主最近比较忙,争取每周翻译 ...

  8. Java类加载机制及自定义加载器

    转载:https://www.cnblogs.com/gdpuzxs/p/7044963.html Java类加载机制及自定义加载器 一:ClassLoader类加载器,主要的作用是将class文件加 ...

  9. java web eclipse中项目的加载过程

    java web eclipse中项目的加载过程: Tomcat默认从WEB-INF/目录下加载资源,Eclipse在发布程序的时候,并没有把User Libraries的相关资源拷贝到WEB-INF ...

随机推荐

  1. Dagger2使用

    初衷 Dagger2的初衷就是通过依赖注入让你少些很多公式化代码,更容易测试,降低耦合,创建可复用可互换的模块.你可以在Debug包,测试运行包以及release包优雅注入三种不同的实现. 依赖注入 ...

  2. Mybatis:通过MapperScannerConfigurer进行mapper扫描

    在applicationContext.xml里配置的

  3. VC中链接错误,提示string重定义

    VC链接错误,说是string已经有了实现了,只要 rebuild 一下好了. Linking...LINK : warning LNK4075: ignoring '/EDITANDCONTINUE ...

  4. cookie操作:设置cookie、读取cookie、删除cookie

    一.设置cookie function setCookie(name, value){ Days = 1; var exp = new Date(); exp.setTime(exp.getTime( ...

  5. laravel视图$errors为空

    最近用laravel5.2的validator时,完全参考手册操作,结果控制器$validator->errors()->all()正常显示错误信息,$validator->fail ...

  6. Haskell语言学习笔记(71)Semigroup

    Semigroup class Semigroup a where (<>) :: a -> a -> a sconcat :: NonEmpty a -> a stim ...

  7. RabbitMQ系列教程之二:工作队列(Work Queues)(转载)

    RabbitMQ系列教程之二:工作队列(Work Queues)     今天开始RabbitMQ教程的第二讲,废话不多说,直接进入话题.   (使用.NET 客户端 进行事例演示)          ...

  8. 使用adb查看CPU和内存

    adb shell ->cat/sys/class/net/wlan0/address 获取Mac地址 abd shell –>cat /proc/cpuinfo 获取CPU信息 adb ...

  9. React/anu实现Touchable

    在RN中有一个叫Touchable 的组件,这里我们重演如何实现它. Touchable存在的意义是屏蔽click的问题.移动端与手机的click 在一些浏览器是有差异,比如说著名的300ms延迟. ...

  10. 12.JDBC-mysql.md

    目录 API简述 Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序 Connection接 ...