Jboss5.1类加载及配置文件读取解密

一般web项目部署在jboss的deploy目录下,其依赖的jar一般在web-inf\lib 里面(以下称warlib),但jboss还提供了一个lib文件即和deploy平行的目录(以下称defaultlib),这里面也可以放jar,按照网上的说法当war里需要的类在自身目录里找不到时就会去defaultlib里面去找(但实际项目中发现并非总是如此,例如涉及xml解析和spring的一些东西的时候)。

那么问题来了,当需要读取配置文件时到底读的哪儿的配置文件呢?总的来说配置文件有以下几个地方

在war的classes里

在war里lib文件夹里

在war的jar里

在defaultlib文件夹下

在defaultlib的jar里

对于上面涉及到jar的情况又分为在自己的jar里和在其他jar里两种情况,于是我写了下面的代码做测试


public class DefaultJar {
	public void print() throws IOException{
		System.out.println("-----"+this.getClass().getName()+"-----");
		ClassLoader parentLoader=null;
		ClassLoader threadLoader=Thread.currentThread().getContextClassLoader();
		System.out.println("ThreadLoader:"+threadLoader);
		parentLoader=threadLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		ClassLoader classLoader=this.getClass().getClassLoader();
		System.out.println(" ClassLoader:"+this.getClass().getClassLoader());
		parentLoader=classLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		System.out.println("     isEqual:"+(threadLoader==classLoader));
		InputStream is=null;
		byte[] data=null;
		is=threadLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from ThreadLoader:"+new String(data));
		is.close();
		is=classLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from  ClassLoader:"+new String(data));
		is.close();
		System.out.println();
	}
}

以上会打包成一个jar并放在defaultlib里,并且在jar里还有一个名字是classLoader的文件,里面写着“defaultjar”,另外在defaultlib里还有一个classLoader文件未被打入jar里,写的是outofjar

public class WarJar {
	public void print() throws IOException{
		System.out.println("-----"+this.getClass().getName()+"-----");
		ClassLoader parentLoader=null;
		ClassLoader threadLoader=Thread.currentThread().getContextClassLoader();
		System.out.println("ThreadLoader:"+threadLoader);
		parentLoader=threadLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		ClassLoader classLoader=this.getClass().getClassLoader();
		System.out.println(" ClassLoader:"+this.getClass().getClassLoader());
		parentLoader=classLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		System.out.println("     isEqual:"+(threadLoader==classLoader));
		InputStream is=null;
		byte[] data=null;
		is=threadLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from ThreadLoader:"+new String(data));
		is.close();
		is=classLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from  ClassLoader:"+new String(data));
		is.close();
		System.out.println();
	}
}

以上打成一个jar放在warlib里,同样在jar里还有个classLoader的配置文件,里面写着“warjar”

还有一个web项目

public class WarClass {
	public void print() throws IOException{
		System.out.println("-----"+this.getClass().getName()+"-----");
		ClassLoader parentLoader=null;
		ClassLoader threadLoader=Thread.currentThread().getContextClassLoader();
		System.out.println("ThreadLoader:"+threadLoader);
		parentLoader=threadLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		ClassLoader classLoader=this.getClass().getClassLoader();
		System.out.println(" ClassLoader:"+this.getClass().getClassLoader());
		parentLoader=classLoader;
		do{
			parentLoader=parentLoader.getParent();
			System.out.println("\tParentLoader:"+parentLoader);
		}while(null!=parentLoader);
		System.out.println("     isEqual:"+(threadLoader==classLoader));
		InputStream is=null;
		byte[] data=null;
		is=threadLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from ThreadLoader:"+new String(data));
		is.close();
		is=classLoader.getResourceAsStream("classLoader");
		data=new byte[is.available()];
		is.read(data);
		System.out.println("data from  ClassLoader:"+new String(data));
		is.close();
		System.out.println();
	}
}

在这个web项目里还有个初始化时就启动的servlet如下

public class InitServlet extends HttpServlet {

	@Override
	public void init() throws ServletException {
		super.init();
		try {
			new WarClass().print();
			new WarJar().print();
			new DefaultJar().print();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
同样在war里也有配置文件,写的是“warclass”

注意以上三个不在同一个package里

放入jboss执行后运行结果:

2016-05-05 14:06:35,884 INFO  [STDOUT] (main) -----com.warclass.WarClass-----
2016-05-05 14:06:35,884 INFO  [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,884 INFO  [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,884 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,884 INFO  [STDOUT] (main)  ClassLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,884 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,884 INFO  [STDOUT] (main)      isEqual:false
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from  ClassLoader:warclass
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) -----qbit.warjar.WarJar-----
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO  [STDOUT] (main)  ClassLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO  [STDOUT] (main)      isEqual:false
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from  ClassLoader:warclass
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) -----qbit.defaultjar.DefaultJar-----
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO  [STDOUT] (main)  ClassLoader:BaseClassLoader@34600d{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/conf/jboss-service.xml}
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO  [STDOUT] (main)      isEqual:false
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO  [STDOUT] (main) data from  ClassLoader:defaultjar


从结果来看:

war和defaultlib里面的class用的是两个classLoader

thread都是同一个classLoader,这个容易想到,但是意外的发现他的classLoader居然是war里的classLoader

至于两个classLoader读取配置文件,war的读取的是classes下面,而defaultlib里面读取的是jar里面另外根据其他的实验表名读取配置名字是读取名字最小的jar里(那就说明未必和读取配置文件代码所在的jar是同一个jar)


你可能感兴趣的:(jboss,ClassLoader,jar,Class,配置文件)