最近项目中遇到在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; ......