有一天,小明想吃苹果,到村里的水果店买到了水果。
第二天,小明想吃苹果,到村里的水果店买水果,老板说:“哎呀不好意思,今天苹果卖完了,要不你去镇上水果店看看?”于是小明跑到镇上的水果店,成功买到了水果。
第三天,小明想吃苹果,到村里的水果店买水果,老板说:“哎呀不好意思,今天苹果卖完了,要不你去镇上水果店看看?”于是小明跑到镇上的水果店,结果发现整个镇上的苹果都卖完了。老板说市里还有苹果卖,小明只能远道去那里买了。
第四天,小明想吃苹果,以防家门口和镇上的水果店都没苹果,就直奔市里。没想到全市的苹果都卖完了。
老板:隔壁城市的水果批发市场还有水果卖,市里的水果店都是在那进货的。
小明连夜买好车票去水果批发市场买苹果。
第五天,小明想吃苹果,直奔市里和隔壁水果批发市场,发现苹果卖完了。
小明只能撞运气,回到镇里的那家水果店,发现这里有所剩不多的苹果。
老板:这我从黑市花了大价钱入的苹果,199一个,你要不要吧(劈瓜脸)。
要。
第六天,市里和镇上(包括黑市和水果批发市场)的苹果全部卖完。
小明回到村里的那家水果店,竟然发现满满一箩筐苹果。
小明问老板:为什么连水果批发市场的苹果都卖完了,你家还有苹果?
老板:哦,这些都是我刚从自己农田里摘的。
行吧。
小例子讲完了,那么这跟提到的双亲委派机制又有什么关系呢?
双亲委派机制的含义就是本层加载器(AppClassLoader)在加载Class文件的时候,优先使用上一层加载器(ExtClassLoader)的缓存去加载,也叫向上委派,如果没有则再用最上层加载器(BootstrapClassLoader)的缓存去加载。
如果所有加载器都没有缓存的话,那就反过来由最上层加载器(BootstrapClassLoader)使用本层加载器类库查找并加载Class文件,如果没有找到就去下一层加载器(ExtClassLoader)使用类库查找并加载,如果还是没有找到就用最下层加载器(AppClassLoader)查找并加载。这个方式就叫做向下查找。
由于BootstrapClassLoader和ExtClassLoader是AppClassLoader的两个父级,因此这个逐级向上托管的行为叫做双亲委派机制。
所以这里就有了对应关系:
- AppClassLoader缓存:村里水果店
- AppClassLoader库:果园
- ExtClassLoader缓存:镇上水果店
- ExtClassLoader库:黑市
- BootstrapClassLoader缓存:市里水果店
- BootstrapClassLoader库:水果批发市场
不难看出,每一家水果店(加载器)都有自己独特的进货渠道(Class类库)。
假设规模越大的水果店,水果的平均品质越好,那么水果批发市场(BootstrapClassLoader)的苹果优先级自然是最高的,市里许多有实力的水果店也会来这里进货(加载Class文件)。
黑市(ExtClassLoader)次之。
农夫果园(AppClassLoader)优先级则最低。
由此进一步可以引申出双亲委派机制的作用:为了安全,避免我们编写自己的类去替换Java的核心类,比如说String类(果园的苹果品质差,而水果批发市场的苹果品质好,小明讲究生活品质,愿意跑大老远去水果批发市场买优质苹果);避免相同的Class类被不同的ClassLoader重复加载(小明既然已经在水果批发市场买到了苹果,就不需要再去黑市买一次了)。