自己开发了一个Classloader,继承自URLClassloader,希望对大家有所帮助
它可以做一般Classloader所必须做的事情,包括
(1)根据Url加载类
(2)如果本地的用file:///协议来获得的URL里面拿字节码的时候,过滤掉file:///
(3)获取字节码
(4)根据类名查找类文件
(5)载入类
- /**
- * @author charles.wang
- *
- */
- public class CustomClassLoader extends URLClassLoader {
- private FileInputStream input = null; //文件输入流
- private ByteArrayOutputStream out = null;//字节数组输出流
- private String[] url = null; //类文件加载路径
- private byte[] data = null; //类文件字节码
- private String extensionName = ""; //类文件扩展名
- /**
- *
- * @param urls : 将被加载的类的url
- */
- public CustomClassLoader(URL[] urls) throws Exception{
- super(urls);
- // TODO Auto-generated constructor stub
- this.url = new String[urls.length];
- for( int i=0;i<urls.length;i++){
- this.url[i] = urls[i].toURI().toString();
- }
- }
- public FileInputStream getInput() {
- return input;
- }
- public void setInput(FileInputStream input) {
- this.input = input;
- }
- public ByteArrayOutputStream getOut() {
- return out;
- }
- public void setOut(ByteArrayOutputStream out) {
- this.out = out;
- }
- public String[] getUrl() {
- return url;
- }
- public void setUrl(String[] url) {
- this.url = url;
- }
- public byte[] getData() {
- return data;
- }
- public void setData(byte[] data) {
- this.data = data;
- }
- public String getExtensionName() {
- return extensionName;
- }
- public void setExtensionName(String extensionName) {
- this.extensionName = extensionName;
- }
- /**
- * 解析URL,将file头去掉
- */
- private void setFilePath(){
- for( int i=0; i<this.url.length;i++){
- if ( this.url[i].substring(0,4).toLowerCase().equals("file") == true){
- this.url[i] = this.url[i].substring(5);
- }
- }
- }
- /**
- * 获得指定类名(全限定类名)文件的字节码
- */
- private byte[] getFileData(String name){
- try{
- this.setFilePath();
- for(String url: this.url){
- String fileName = url + name.replace(".","\\").concat(".")+ this.getExtensionName();
- input = new FileInputStream( new File(fileName));
- if(input != null){
- break;
- }
- }
- out = new ByteArrayOutputStream();
- data = new byte[1024];
- int len = -1;
- while ( (len = input.read(data)) != -1){
- out.write(data,0,len);
- }
- data = out.toByteArray();
- }catch(Exception e){
- e.printStackTrace();
- }finally{
- try {
- if (input != null)
- input.close();
- if (out != null)
- out.close();
- return data;
- }catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
- }
- /**
- * 根据指定的类名查找类文件
- * @param name
- * @return
- */
- protected Class findClassByName (String name){
- try{
- byte [] data = this.getFileData(name);
- if (data == null){
- return null;
- }
- return this.defineClass(name, data, 0,data.length);
- }catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 重新写 loadClass() 方法
- */
- public Class loadClass (String name){
- Class c = null;
- try{
- c = super.loadClass(name);
- }catch (ClassNotFoundException e){
- e.printStackTrace();
- }finally {
- if (c ==null ){
- //父类的默认方法没有加载到指定类的话,那么使用自定义的方法去查找
- c = this.findClassByName(name);
- }
- return c;
- }
- }
- }
补上使用代码:
- /**
- * @author charles.wang
- *
- */
- public class MainTest {
- /**
- * @param args
- */
- public static void main(String[] args) throws Exception {
- // TODO Auto-generated method stub
- URL[] url = new URL[]{new URL("file:d:\\")};
- //添加想要加载的类路径,网络或者本地均可
- CustomClassLoader csl = new CustomClassLoader(url);
- csl.setExtensionName("class");
- Class cl = csl.loadClass("com.Demo");
- Object obj = cl.newInstance();
- Method method = cl.getMethod("printText", null);
- method.invoke(obj, null);
- }
- }