0

最近在看Java虚拟机,类加载器那节举了这么一个例子:

/**
*类加载器与instanceof关键字演示
**
@author zzm
*/
public class ClassLoaderTest{
    public static void main(String[]args) throws Exception{
        ClassLoader myLoader=new ClassLoader(){
            @Override
            public Class<?>loadClass(String name)throws ClassNotFoundException{
                try{
                    String fileName=name.substring(name.lastIndexOf(".")+1)+".class";
                    InputStream is=getClass().getResourceAsStream(fileName);
                    if(is==null){
                        return super.loadClass(name);
                    }
                    byte[]b=new byte[is.available()];
                    is.read(b);
                    return defineClass(name,b,0,b.length);
                }
                catch(IOException e){
                    throw new ClassNotFoundException(name);
                }
            }
        }
        ;
        Object obj=myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").newInstance();
        System.out.println(obj.getClass());
        System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);//false
    }
}

总而言之就是用自定义的类加载器去加载一个类,返回的类与jvm自带的SystemClassLoader加载的类不同。

那么如果用一个继承自ClasserLoader的类,按理说也是同样的效果

package jvm;
public class MyClassLoader extends ClassLoader{

    @Override
    public Class<?> loadClass(String fullClassName) throws ClassNotFoundException{
        try {
            String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
            InputStream is = getResourceAsStream(fileName);

            if(is==null){
                return super.loadClass(fullClassName);
            }

            byte[] bytes = new byte[is.available()];
            is.read(bytes);

            return defineClass(fullClassName,bytes,0,bytes.length);
        }catch (Exception e){
            throw new ClassNotFoundException();
        }
    }

    public static void main(String[] args) throws Exception{

        ClassLoader myClassLoader = new MyClassLoader();

        /**
        ClassLoader myClassLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String fullClassName) throws ClassNotFoundException {
                try {
                    String fileName = fullClassName.substring(fullClassName.lastIndexOf(".")+1,fullClassName.length())+".class";
                    InputStream is = getClass().getResourceAsStream(fileName);

                    if(is==null){
                        return super.loadClass(fullClassName);
                    }

                    byte[] bytes = new byte[is.available()];
                    is.read(bytes);

                    return defineClass(fullClassName,bytes,0,bytes.length);
                }catch (Exception e){
                    throw new ClassNotFoundException();
                }
            }
        };
        /**/

        ClassLoader systemClassLoader = java.lang.ClassLoader.getSystemClassLoader();

        Class myClass = myClassLoader.loadClass("jvm.MyClassLoader");
        Class systemClass = systemClassLoader.loadClass("jvm.MyClassLoader");

        Object myObj = myClass.newInstance();
        Object systemObj = systemClass.newInstance();

        System.out.println(myClass.equals(systemClass));//true
        System.out.println(myObj.getClass().equals(systemObj.getClass()));//true

    }
}

注释里的代码就是匿名内部类的继承,注意到这里myClass和systemClass是完全相等的,但是myClass是使用继承自ClassLoader的类MyClassLoader生成的,请问这是为什么呢。。。

1 个回答

0

第二个代码走到

if(is==null){
    return super.loadClass(fullClassName);
}

加载class文件用getClass().getResourceAsStream