最後一个类别载入器是Bootstrap Loader , 我们可以经由查询由系统参数sun.boot.class.path 得知Bootstrap Loader 用来搜寻类别的路径。该路径的修改与ExtClassLoader的相同。但修改后不影响Bootstrap的搜寻路径。
0 I' k, U8 |/ W* T6 j 在命令列下参数时,使用–classpath / -cp / 环境变数CLASSPATH 来更改AppClassLoader! |# G( Q# X- A
的搜寻路径,或者用–Djava.ext.dirs 来改变ExtClassLoader 的搜寻目录,两者都是有意义的。
. @, X: a4 A1 [* r6 z1 `. J2 j0 f 可是用–Dsun.boot.class.path 来改变Bootstrap Loader 的搜寻路径是无效。这是因为, x$ I- Y! L% U& k5 U s y' ~
AppClassLoader 与ExtClassLoader 都是各自参考这两个系统参数的内容而建立,当您在命令列下
% s. u9 s0 x0 v4 |" c 变更这两个系统参数之後, AppClassLoader 与ExtClassLoader 在建立实体的时候会参考这两个系0 n1 E! k' U& x5 g/ s) S
统参数,因而改变了它们搜寻类别档的路径;而系统参数sun.boot.class.path 则是预设与
, s$ l/ D, j7 ~1 Z# J8 ] Bootstrap Loader 的搜寻路径相同,就算您更改该系统参与,与Bootstrap Loader 完全无关。
0 H \- D* O9 O' m- w- i5 K 改变java.exe所使用的jre会改变Bootstrap Loader的搜寻路径。: H' R |3 {( _$ E0 v
Bootstrap Loader的搜寻路径一般如下:
( w5 z0 z) J& H; ~8 B ///////////////////////////////////////////////////////////////////////////////////
& a7 o: P* o: |! \9 g' R) I0 X D:\myjava\j2sdk1.4.2_04\jre\lib\rt.jar;D:\myjava\j2sdk1.4.2_04\jre\lib\i18n.jar;# Z# b$ }6 }. f6 O. h! I7 U, `
D:\myjava\j2sdk1.4.2_04\jre\lib\sunrsasign.jar;D:\myjava\j2sdk1.4.2_04\jre\lib\j( {( I; |7 \% X9 `
sse.jar;D:\myjava\j2sdk1.4.2_04\jre\lib\jce.jar;D:\myjava\j2sdk1.4.2_04\jre\lib\
, ?) X3 C* I; d$ f# g3 X charsets.jar;D:\myjava\j2sdk1.4.2_04\jre\classes
5 {7 x# g; P$ A7 t /////////////////////////////////////////////////////////////////////////////////////// }8 D" t( ^. I. C2 n
更重要的是,AppClassLoader 与ExtClassLoader 在整个虚拟机器之中只会存有一份,一旦建
( d. |3 ]8 ]7 ?, K2 J, V( A 立了,其内部所参考的搜寻路径将不再改变,也就是说,即使我们在程式里利用System.setProperty()
4 {, p5 R0 a* M% O 来改变系统参数的内容,仍然无法更动AppClassLoader 与ExtClassLoader 的搜寻路径。因此,执
- a7 _: G3 N, Z. S( E, K9 r 行时期动态更改搜寻路径的设定是不可能的事情。如果因为特殊需求,有些类别的所在路径并非在
+ E: z' E7 M2 ?' r 一开始时就能决定,那麽除了产生新的类别载入器来辅助我们载入所需的类别之外,没有其他方法了。' X1 f( V* c' J" y3 B+ r0 r) \1 \
下面我们将看一下载入器的委派模型
# F6 W# \2 j8 L% k 所谓的委派模型,用简单的话来讲,就是「类别载入器有载入类别的需求时,会先请示其Parent 使用其搜寻路径帮忙载入,如果Parent 找不到,那麽才由自己依照自己的搜寻路径搜寻类别」。$ A9 X; Q5 L8 T! k! p& Q
下面我们看一下小的示例:2 a7 S. F8 V [0 `3 Q( C# q% _
public class Test
% l9 q* O* E2 V2 H2 n1 j {. B# P1 q1 R* c8 l+ E
public static void main(String[] args)
: a9 O1 H) _% c# n4 ^6 p3 H) ? {
Z A2 o( c0 w4 w( l3 _; K System.out.println(Test.class.getClassLoader());2 B7 \4 `7 q/ w: Q& Q& H8 k% M
TestLib tl = new TestLib();7 P# K& z6 t: @6 }) {. [1 M
tl.start();
) i; J% K& X' \) k1 n$ e- p) m }
! k e, W- H3 t$ B, u4 d }
; Z% [; K9 c. c& [0 C public class TestLib, h& } e; h1 Z2 U1 J: A/ G( J
{ l8 y+ I- N: R: p- }
public void start()" a2 Q( t$ w) q% _- ?4 j$ W5 S
{3 g0 B* L7 G/ d
System.out.println(this.getClass().getClassLoader());
% W9 O; y! y* J9 O+ ?+ s W }3 O4 |* ]. T$ p
}
; U5 I) ^* p# f3 D' c1 D6 x 如果这两个类仅放在dos命令提示符的当前目录下,则输出结果如下:: R0 {8 ?9 v. j8 D6 K! K5 T
//////////////////////////////////////////////////////
; v' U1 U5 h7 e2 ] sun.misc.Launcher$AppClassLoader@1a0c10f/ z% @, r4 z( t' M- l$ H5 M
sun.misc.Launcher$AppClassLoader@1a0c10f
1 W+ L+ q3 D" e' ~ //////////////////////////////////////////////////////
& m( ^2 ?! M1 y% k 如果这两个类同时又放在\lib\ext\classes 底下(在我的机器上是:D:\myjava\j2sdk1.4.2_04\jre\lib\ext\classes,classes没有,需要自己建),输出结果如下:
3 |5 v. B" d* d /////////////////////////////////7 A7 c1 Z( \. g
sun.misc.Launcher$ExtClassLoader@e2eec8% B" f# K- X) y! r0 G4 U
sun.misc.Launcher$ExtClassLoader@e2eec8' S, T/ e& Z% h2 i( k9 s, q* d( \
////////////////////////////////////# `* w: ]9 k" `
最后如果在\classes下放入这两个类,则输出结果为8 o. L( ?1 A1 Y$ U+ y. r
/////////////////////////////////
- ?2 i# S" o; n1 v null3 J- V6 x" h& Q
null% _ E x- `, `# {8 L1 ]% T# g2 l
////////////////////////////////////5 s: Y' t$ V. q+ N2 W
如果把\classes下的TestLib删去,则输出入下:
. K- b, C7 n! c& M7 { w8 Z //////////////////////////////////////
" b; S7 N" M9 j* Q* d null
" c( W) E& x: \( v [( T+ x: B! y Exception in thread "main" java.lang.NoClassDefFoundError: TestLib5 R1 B' Z2 Z+ g' t
at Test.main(Test.java:7)3 c: w/ `) `6 N) W- [6 k
//////////////////////////////////////
" q' Z. Q7 { `; X! T6 ] 这是因为Test的classLoader是Bootstrap Loader ,因此TestLib的也默认为是Bootstrap Loader。Bootstrap Loader搜寻路径下的TestLib被删去了,Bootstrap Loader又没有parent,所以提示找不到。* M0 K, b: W0 j& v L
其他的情况可以自己逐个添加或删除文件,然后执行java Test进行测试,察看输出结果。3 o3 N- ~$ D' o
AppClassLoader 与Bootstrap Loader会搜寻它们所指定的位置(或JAR 档),如果找不到就找不到了,AppClassLoader 与Bootstrap Loader不会递回式地搜寻这些位置下的其他路径或其他没有被指定的JAR 档。反观ExtClassLoader,所参考的系统参数是java.ext.dirs,意思是说,他会搜寻底下的所有JAR 档以及classes 目录,作为其搜寻路径。 |