初学Java的人经常遇到的一个问题是:如果一个程序依赖某个文件夹下的一堆jar包,那么启动它的时候就需要在java -cp参数后面一个一个的加上jar包的名称,很不方便。
比如主程序类叫Main,在目录lib下有aaa.jar,bbb.jar,ccc.jar,则需要输入以下命令才能执行:java -cp lib/aaa.jar;lib/bbb.jar;/lib.ccc.jar Main
(linux系统下用冒号,windows下用分号)。
如果jar包少,倒也不是很麻烦,但如果依赖的jar包数量很多的话,一个个的输就比较麻烦了,当然我们也可以借助一些脚本或者Ant来实现自动化,但总觉得杀鸡焉用牛刀,反而把事情弄麻烦了。
我自己是这样解决的:
java -Djava.ext.dirs=./lib -cp ./bin Main (假设主程序类Mian.class放在bin目录下)
正如你说看到的,-Djava.ext.dirs起到了关键作用,它将告诉JVM从那里加载一些类,为了方便理解记忆,顺便补充一点ClassLoader的常识:
Java的类装载模型是一种代理(delegation)模型。当JVM 要求类装载器CL(ClassLoader)装载一个类时,CL首先将这个类装载请求转发给他的父装载器。只有当父装载器没有装载并无法装载这个类时,CL才获得装载这个类的机会。这样, 所有类装载器的代理关系构成了一种树状的关系。树的根是类的根装载器(bootstrap ClassLoader) , 在JVM 中它以"null"表示。除根装载器以外的类装载器有且仅有一个父装载器。在创建一个装载器时, 如果没有显式地给出父装载器, 那么JVM将默认系统装载器为其父装载器。
根(Bootstrap) 装载器:该装载器没有父装载器,它是JVM实现的一部分,从sun.boot.class.path装载运行时库的核心代码。
扩展(Extension) 装载器:继承的父装载器为根装载器,不像根装载器可能与运行时的操作系统有关,这个类装载器是用纯Java代码实现的,它从java.ext.dirs (扩展目录)中装载代码。(这一段就是为什么可以通过设置-Djava.ext.dirs来加载一堆jar的原理)