欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jvm解析二(自定义加载器)

程序员文章站 2022-06-07 17:12:43
...
自定义加载器<code>
3个类LoaderTest01.java, LoaderTest02.java,MyClassLoader.java
1, MyClassLoader 
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader  extends ClassLoader{
	
	private String name;
	private String path;
    private final String fileType=".class";
    public MyClassLoader(String name){
    	super();
    	this.name=name;
    }
   public MyClassLoader(ClassLoader parent,String name){
	   super(parent);
	   this.name=name;
   }
	@Override
	public String toString() {
		
		return this.name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public String getFileType() {
		return fileType;
	}
	
	private byte[] loadClassData(String name) {
       InputStream in=null;
       byte [] data=null;
       ByteArrayOutputStream bs=null;
       try{
    	   System.out.println("name="+this.name);
    	   this.name=this.name.replace(".", "\\");
           in=new FileInputStream(new File(path+name+fileType));
           bs=new ByteArrayOutputStream();
           int k=0;
           while((k=in.read())!=-1){
        	   bs.write(k);
           }
           data=bs.toByteArray();
       }catch(Exception e){
    	 e.printStackTrace();   
       }finally{
    	   try {
    		in.close();
			bs.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
       }
       
       return data;
    }
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte [] data=this.loadClassData(name);
		
		return this.defineClass(name, data, 0,data.length);
	}
	
     public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
    	 MyClassLoader loader01=new MyClassLoader("loader01");
    	 loader01.setPath("d:\\loader\\lib1\\");
    	 
    	 MyClassLoader loader02=new MyClassLoader(loader01,"loader02");
    	 loader02.setPath("d:\\loader\\lib2\\");
    	 
    	 MyClassLoader loader03=new MyClassLoader(null,"loader03");
    	 loader03.setPath("d:\\loader\\otherlib3\\");
    	 
    	 load(loader02);
    	 load(loader03);
     }
   
     public static void load(ClassLoader loader) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
    	 Class c=loader.loadClass("LoaderTest01");
         Object object=c.newInstance();
     }
}

2, LoaderTest01
public class LoaderTest01 {

	public LoaderTest01() {
	   System.out.println("LoaderTest01 is loader by :"+this.getClass().getClassLoader());
	   new LoaderTest02();
	}

}

3, LoaderTest02
public class LoaderTest02 {

	public LoaderTest02() {
		   System.out.println("LoaderTest02 is loader by :"+this.getClass().getClassLoader());

	}

}

第一种情况文件按照下面位置放置
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
运行结果如下:
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
分析:当执行load(loader02)这句语句的时候,会优先去找它的父加载器loader01, 而loader01又回去找它的父类是系统加载器,系统加载器会根据classpath来查找所要加载的类,发现没有,接着由loader01去加载,loader01加载的时候找到文件执行接下操作,而LoaderTest01里主动使用了new LoaderTest02(), LoaderTest02也会根据上面的方式去找,跟LoaderTest01结果是一样的。
     当执行load(loader03)这句语句的时候,由于父类加载器是null默认为根加载器,根加载器会去sun.boot.class.path的里面去找没有找到,最后由loader3自己去加载。
第二种情况文件按照下面位置放置
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
运行结果如下:
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
分析:当执行load(loader02)的时候,会优先去找它的父加载器loader01, 而loader01又回去找它的父类是系统加载器,系统加载器会根据classpath来查找所要加载的类,发现没有,接着由loader01去加载,loader01加载的时候找到文件执行接下操作,而LoaderTest01里主动使用了new LoaderTest02(), LoaderTest02也会执行上面同样的步骤, 但是LoaderTest01和LoaderTest02位于2个不同的加载器空间下,而他们之间是互相不可见的(他们的父子关系并不是继承,也有可能是组合,但是他们都是系统加载器的子类,对系统加载器里的资源都是共享的),所以在Loader01加载器加载的时候无法获取LoaderTest02
第三种情况:
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
运行结果如下:
jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
分析:当执行load(loader02)的时候,会优先去找它的父加载器loader01, 而loader01又回去找它的父类是系统加载器,系统加载器会根据classpath来查找所要加载的类,并在当前目录下发现了这2个类,并执行操作,前2个加载器均为系统加载器,虽然lib1和lib2下2个文件在不同的类加载器空间下,但是实际执行并不需要它们,在系统一级已经执行完毕,而第三个,当执行load(loader03)的时候,父加载器null默认为根加载器,根加载器无法在相应的目录里找到相应的文件,于是交由其他加载器实现,而此时loader03加载器在相应的otherlib3下也无法找到相应的文件于是报错。
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 14.8 KB
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 3 KB
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 16.3 KB
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 6.5 KB
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 16.9 KB
  • jvm解析二(自定义加载器)
            
    
    博客分类: java虚拟机 jvmClassLoader
  • 大小: 3.9 KB
相关标签: jvm ClassLoader