最近项目中遇到在Tomcat7.0.26中类加载顺序不稳定的情况,github上拉了源码看了下搞明白了。项目中的问题是,我们可以通过字母顺序定义jar文件在webapp\WEB-INF\lib下的加载顺序,但是在tomcat\lib\ext下就不灵了。其实问题在于这两个位置的jar, tomcat是用的不同的classloader去加载的,所以结果自然不同。
对于common和system class,tomcat使用的是org.apache.catalina.startup.ClassLoaderFactory产生的classloader,入口在Bootstrap.initClassLoaders()。这个classloader里面遍历文件夹下的jar文件时使用的是java api: File.list()。看javadoc对顺序的解释。
* <p> There is no guarantee that the name strings in the resulting array
* will appear in any specific order; they are not, in particular,
* guaranteed to appear in alphabetical order.
而在WebappClassloader中,tomcat对于File.list()取到的列表又做了一次字母顺序排序。
org.apache.naming.resources.FileDirContext
protected List<NamingEntry> list(File file) {
List<NamingEntry> entries = new ArrayList<NamingEntry>();
if (!file.isDirectory())
return entries;
String[] names = file.list();
if (names==null) {
/* Some IO error occurred such as bad file permissions.
Prevent a NPE with Arrays.sort(names) */
log.warn(sm.getString("fileResources.listingNull",
file.getAbsolutePath()));
return entries;
}
Arrays.sort(names); // Sort alphabetically
NamingEntry entry = null;
......