gembin

OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

HBase, Hadoop, ZooKeeper, Cassandra

Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

About Me

 

java.library.path属性在代码中设置不生效问题

from http://daimojingdeyu.blogbus.com/logs/28617218.html



可是在使用上面文章介绍的动态库时,遇上了加载问题,也就是将动态库放到什么位置合适?文章中说可以放到System32目录,但我不想这样做,我更希望的是可以自己定制dll库的位置~~

没有将lib放到System32目录,而是放到了自己的lib目录,程序在启动的过程中会报下面的错误:
java.lang.UnsatisfiedLinkError: no JIntellitype in java.library.path

根据上面的提示信息在VM参数处通过-Djava.library.path将加载路径指定到自己的lib目录后,程序可以正常启动。

这种方式不是太好,因为要手动的去指定虚拟机参数,于是想通过System类的setProperty函数来在代码中动态的改变一下java.library.path的值。
使用
Java代码 复制代码
  1. System.setProperty("java.library.path""./lib");  

后,启动程序总是报错"no JIntellitype in java.library.path"

想了半天没有想明白,为什么代码的设置就不起作用,而在虚拟机参数处指定就是好的?

Google了半天才知道原因,这里整理一下,以方便以后查找。
代码中设置不起作用,主要是因为java.library.path只在jvm启动时读取一次,其他情况下的修改不会起作用的。可以参考下面的这个bug:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4280189

原因和ClassLoader的实现有关系,
ClassLoader.loadLibrary() method:
Java代码 复制代码
  1. if (sys_paths == null) {  
  2.         usr_paths = initializePath("java.library.path");  
  3.         sys_paths = initializePath("sun.boot.library.path");  
  4. }  


系统缓存了java.library.path的值,并且一直都会是第一次加载时的值。有人提到了下面的修改方法,
Java代码 复制代码
  1. if (sys_paths == null) {  
  2.        sys_paths = initializePath("sun.boot.library.path");  
  3. }  
  4. usr_paths = initializePath("java.library.path");  

但是从2002年到现在Sun一直都没有改,不知道出于什么原因考虑的。

有问题,就会有人解决问题,antony_miguel在一篇文章中,使用java的反射机制,完成了对于ClassLoader类中的usr_paths变量的动态修改,
Java代码 复制代码
  1. public static void addDir(String s) throws IOException {  
  2.     try {  
  3.         Field field = ClassLoader.class.getDeclaredField("usr_paths");  
  4.         field.setAccessible(true);  
  5.         String[] paths = (String[])field.get(null);  
  6.         for (int i = 0; i < paths.length; i++) {  
  7.             if (s.equals(paths[i])) {  
  8.                 return;  
  9.             }  
  10.         }  
  11.         String[] tmp = new String[paths.length+1];  
  12.         System.arraycopy(paths,0,tmp,0,paths.length);  
  13.         tmp[paths.length] = s;  
  14.         field.set(null,tmp);  
  15.     } catch (IllegalAccessException e) {  
  16.         throw new IOException("Failed to get permissions to set library path");  
  17.     } catch (NoSuchFieldException e) {  
  18.         throw new IOException("Failed to get field handle to set library path");  
  19.     }  
  20. }  

文章也同时指出了这种实现的局限性,和jvm的实现强关联,只要jvm实现不是用的变量usr_paths来保存java.library.path的值,这个方法就不能用了。
但是只要知道源代码,小小的改动就应该可以实现了。

posted on 2008-10-29 14:49 gembin 阅读(7595) 评论(0)  编辑  收藏 所属分类: JavaSE


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

常用链接

留言簿(6)

随笔分类(440)

随笔档案(378)

文章档案(6)

新闻档案(1)

相册

收藏夹(9)

Adobe

Android

AS3

Blog-Links

Build

Design Pattern

Eclipse

Favorite Links

Flickr

Game Dev

HBase

Identity Management

IT resources

JEE

Language

OpenID

OSGi

SOA

Version Control

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜

free counters