在可执行jar 包中动态载入第三方jar class的有关问题

来源:互联网 发布:未能完成mac os x安装 编辑:程序博客网 时间:2024/05/22 17:05

一、前言

 

 

在商业化开发中经常是将开发的类打成jar包发布.由于有很多第三方的提供功能集合Jar包,所以经常会用到这些功能包.以下情景是很多Java开发人员经常碰到的:在开发,调试阶段,通过在CLASSPATH中设置第三方的jar包路径,自己编写的class工作正常.开发完毕,部署的时候,将开发的class打成一个可执行jar包,会发现通过Class.forName(String classname) 或ClassLoader.getSystemClassLoader().loadClass(String classname)来动态载入存在于第三方jar包中的class会抛出异常” ClassNotFoundException.

这种问题存在于通过jar –jar yourself.jar 来运行jar包,并在jar中的class中通过Class.forName(String classname)来动态载入第三方的class的时候.

常见的应用,比如根据用户的选择配置,动态载入不同厂商的JDBC Driver.

 

 

二、背景知识

 

自JDK 1.2以后,JVM采用了委托(delegate)模式来载入class.采用这种设计的原因可以参考http://java.sun.com/docs/books/tutorial/ext/basics/load.html

归纳来讲:是基于JVM sandbox(沙盒)安装模型上提供应用层的可定制的安全机制.

 

三、Java虚拟机(JVM)寻找Class的顺序

 

3.1 Bootstrap classes

属于Java 平台核心的class,比如java.lang.String等.及rt.jar等重要的核心级别的class.这是由JVM Bootstrap class loader来载入的.一般是放置在{java_home}/jre/lib目录下

3.2 Extension classes

基于Java扩展机制,用来扩展Java核心功能模块.比如Java串口通讯模块comm.jar.一般放置在{Java_home}/jre/lib/ext目录下

3.3 User classes

开发人员或其他第三方开发的Java程序包.通过命令行的-classpath或-cp,或者通过设置CLASSPATH环境变量来引用.JVM通过放置在{java_home}/lib/tools.jar 来寻找和调用用户级的class.常用的javac也是通过调用tools.jar来寻找用户制定的编译Java源程序.这样就引出了User class路径搜索的顺序或优先级别的问题.

3.3.1 缺省值:调用Java或javawa的当前路径(.),是开发的class所存在的当前目录

3.3.2 CLASSPATH环境变量设置的路径.如果设置了CLASSPATH,则CLASSPATH的值会覆盖缺省值

3.3.3 执行Java的命令行-classpath或-cp的值,如果制定了这两个命令行参数之一,它的值会覆盖环境变量CLASSPATH的值

3.3.4 -jar 选项:如果通过java –jar 来运行一个可执行的jar包,这当前jar包会覆盖上面所有的值.换句话说,-jar 后面所跟的jar包的优先级别最高,如果指定了-jar选项,所有环境变量和命令行制定的搜索路径都将被忽略.JVM APPClassloader将只会以jar包为搜索范围.有关可执行jar有许多相关的安全方面的描述,可以参考http://java.sun.com/docs/books/tutorial/jar/ 来全面了解.

这也是为什么应用程序打包成可执行的jar包后,不能引用第三方jar包的原因.

 

四、解决方案.

 

首先我们简要归纳一下,为了方便理解,简化一下上面描述的架构,

Java定义了三种级别的class,分别为BootStrap class,Extend Class,User class.

其中User class限制规则最复杂.在User class中可执行的jar包,更包含独立安全规则.所以解决方案基于Java三种不同级别的class扩展机制,有三种不同的方案.

 

4.1 BootStrap class扩展方案

Java 命令行提供了如何扩展bootStrap 级别class的简单方法.

-Xbootclasspath:基本核心的Java class 搜索路径.不常用,否则要重新写所有Java 核心class

-Xbootclasspath/a: 后缀在核心class搜索路径后面.常用.

-Xbootclasspath/p:前缀在核心class搜索路径前面.不常用,避免引起不必要的冲突.

 

语法如下:

java –Xbootclasspath/a:/path/myclass/account.jar: -jar yourself.jar(Unix用:号隔开)

java –Xbootclasspath:/d:/myclass/account.jar; -jar yourself.jar(Window用;号隔开)

 

4.2 extend class 扩展方案

Java exten class 存放在{Java_home}/jre/lib/ext 目录下.当调用Java时,对扩展class路径的搜索是自动的.总会搜索的.这样,解决的方案就很简单了,将所有要使用的第三方的jar包都复制到ext 目录下.

 

4.3 User class扩展方案

当使用-jar执行可执行Jar包时,JVM将Jar包所在目录设置为codebase目录,所有的class搜索都在这个目录下开始.所以如果使用了其他第三方的jar包,一个比较可以接受的可配置方案,就是利用jar包的Manifest扩展机制.步骤如下

1.将需要的第三方的jar包,复制在同可执行jar所在的目录或某个子目录下.

比如:jar 包在 d:/crm/luncher.jar 那么你可以把所有jar包复制到d:/crm目录下或d:/crm/lib 子目录下.

2.修改Manifest 文件

在Manifest.mf文件里加入如下行

Class-Path:classes12.jar lib/class12.jar

Class-Path 是可执行jar包运行依赖的关键词.详细内容可以参考http://java.sun.com/docs/books/tutorial/ext/index.html

 

另外编写自己的ClassLoader,来动态载入class,是更加复杂和高级技术.限于篇幅,不赘述.有兴趣了解可以去google一下custom classloader

 

4.4 推荐方案 4.1,扩展性非常好.

 

五、总结

 

Java的安全机制随不同的JDK版本有不同的变化,会影响很多核心CLASS,比如Thread,所以很多大型商业软件,要求JDK的版本很严格.部分原因也在此.这也要求在发布自己编写的应用时候,不管大小,都要说明开发和测试的JDK版本.

本文所测试基于jdk 1.4.1_03 for windows 。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 打老鼠被老鼠咬了了怎么办 制作棒棒糖时木棍翘起怎么办 兔子被打后怕我怎么办 兔子后腿摔断了怎么办 兔子腿骨头断了怎么办 减肥老是控制不住吃怎么办 不爱吃主食爱吃零食怎么办 猫咪奶涨的很硬怎么办 斩魂技能乱加的怎么办 狗狗不吃东西还拉稀怎么办 狗狗拉稀不吃饭怎么办 狗狗几天不吃东西怎么办 狗狗不吃不喝怎么办 拖鞋洗了有臭味怎么办 拖鞋湿水了很臭怎么办 棉被上渗了酸奶怎么办 酸奶弄在衣服上怎么办 孩子把褥子尿湿怎么办 小孩尿过的褥子怎么办 包包放着发霉了怎么办 被套盖久了发黄怎么办 小白鞋里面发霉怎么办 棉被淋了一点雨怎么办 苹果手机被拉进电话群怎么办 墙上的插座烧了怎么办 富士康早退4分钟怎么办 我老婆起泡疹腿剌痛睡不着了怎么办 oppo耳机孔坏了怎么办 魅族耳机口坏了怎么办 控制线的报验资料怎么办 人失踪报警派出所不管怎么办 铁板的货架久了怎么办 干镀锌让环保查了怎么办 水管软管生锈了拧不动怎么办 镀锌管会生锈吗.怎么办 冷镀锌钢管生锈了怎么办 卖了过期的东西怎么办 喝到了假的饮料怎么办 烧汤总是溢锅怎么办 脚踩垃圾桶坏了怎么办 连衣裙特别容易起褶怎么办