类加载器测试--类加载器(二)

类加载器测试

1.测试加载文件路径
public class ClassloaderTest {
     
      public static void main(String[] args) {
          //启动类加载器加载类的文件
          System. out .println(System.getProperty( "sun.boot.class.path" ));
          //扩展类加载器加载类的文件  
          System. out .println(System.getProperty( "java.ext.dirs" ));
          //系统类加载器加载类的文件
          System. out .println(System.getProperty( "java.class.path" ));
     }
}

结果显示:
C:\Program Files\Java\jdk1.7.0_17\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\sunrsasign.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_17\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_17\jre\classes
C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
E:\eclipsenew\workspace\RedisTest\bin;C:\Users\***\.m2\repository\ redis\clients\jedis\2.6.0\jedis-2.6.0.jar

2.测试classloader体系结构

public class ClassloaderTest {
      public static void main(String[] args) throws Exception {
          System. out .println(Thread.currentThread().getContextClassLoader());
          System. out .println(ClassloaderTest. class .getClassLoader());
          System. out .println(System. class .getClassLoader());
          System. out .println(ClassLoader.getSystemClassLoader());
          System. out .println(ClassLoader.getSystemClassLoader().getParent());
          System. out .println(ClassLoader.getSystemClassLoader().getParent().getParent());
     }
}

结果显示:
sun.misc.Launcher$AppClassLoader@533e846f
sun.misc.Launcher$AppClassLoader@533e846f
null
sun.misc.Launcher$AppClassLoader@533e846f
sun.misc.Launcher$ExtClassLoader@2d68be1b
null
System.java这样的由系统提供的类都在rt.jar中,由Bootstrap ClassLoader加载,由于Bootstrap类加载器不是Java写的,所以打印出来的类名为null

3.测试类的类加载器
package sms;
public class ClassloaderTest {
      public static void main(String[] args) throws Exception {
          ClassLoader cl = ClassLoader.getSystemClassLoader();
          System. out .println(cl);
           while (cl != null ) {
              cl = cl.getParent();
              System. out .println(cl);
          }
           try {
              Class c = Class.forName( "java.lang.Object" );
              cl = c.getClassLoader();
              System. out .println( "java.lang.Object's loader is  " + cl);
              c = Class.forName( "sms.ClassloaderTest" );
              cl = c.getClassLoader();
              System. out .println( "ClassloaderTest's loader is  " + cl);
          }
           catch (Exception e) {
              e.printStackTrace();
          }
     }
}

结果显示:
sun.misc.Launcher$AppClassLoader@533e846f
sun.misc.Launcher$ExtClassLoader@2d68be1b
null
java.lang.Object's loader is  null
ClassloaderTest's loader is  sun.misc.Launcher$AppClassLoader@533e846f

第一行表示,系统类装载器实例化自类sun.misc.Launcher$AppClassLoader

第二行表示,系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader

第三行表示,系统类装载器parent的parent为bootstrap

第四行表示,核心类java.lang.Object是由bootstrap装载的

第五行表示,用户类LoaderSample1是由系统类装载器装载的

4.自定义classloader (一)

public class ClassLoaderTest1 extends ClassLoader {
      private ClassLoader parent = null ;
      private String path ;
      public ClassLoaderTest1(String path) {
           this . path = path;
     }
      public ClassLoaderTest1(ClassLoader parent, String path) {
           super (parent);
           this . parent = parent;
           this . path = path;
     }
      @Override
      public Class<?> loadClass(String name) throws ClassNotFoundException {
          System. out .println( "name:" + name);
          Class<?> cls = findLoadedClass(name);
           if (cls == null ) {
              ClassLoader parent2 = getParent().getParent();
               try {
                    //System.out.println("parent2 : " + parent2);
                   System. out .println( "try to use ExtClassLoader to load class : " + name);
                   cls = parent2.loadClass(name);
                   System. out .println( "real cls : " + cls);
                   System. out .println( "real ClassLoader : " + cls.getClassLoader());
              }
               catch (ClassNotFoundException e) {
                   System. out .println( "ExtClassLoader.loadClass :" + name + " Failed" );
              }
               if (cls == null ) {
                   System. out .println( "try to ClassLoaderTest1 load class : " + name);
                   cls = findClass(name);
                    if (cls == null ) {
                        System. out .println( "ClassLoaderTest1.loadClass :" + name + " Failed" );
                   }
                    else {
                        System. out .println( "ClassLoaderTest1.loadClass :" + name + " Successful" );
                        System. out .println( "real ClassLoader : " + cls.getClassLoader());
                   }
              }
               else {
                   System. out .println( "ExtClassLoader.loadClass :" + name + " Successful" );
                   System. out .println( "real ClassLoader : " + cls.getClassLoader());
              }
          }
           return cls;
     }
      @Override
      protected Class<?> findClass(String name) throws ClassNotFoundException {
          System. out .println( "try findClass " + name);
          InputStream is = null ;
          Class class1 = null ;
           try {
              String classPath = name.replace( "." , "\\" ) + ".class" ;
              String classFile = path + classPath;
              System. out .println( "classFile:" +classFile);
               byte [] data = getClassFileBytes(classFile);
              System. out .println( "class1 begin :" +class1);
              class1 = defineClass(name, data, 0, data. length );
              System. out .println( "class1 end :" +class1);
               if (class1 == null ) {
                   System. out .println( "ClassLoaderLK.findClass() ERR " );
                    throw new ClassFormatError();
              }
          }
           catch (FileNotFoundException e) {
              e.printStackTrace();
          }
           catch (IOException e) {
              e.printStackTrace();
          }
           catch (Exception e) {
              e.printStackTrace();
          }
           finally {
               if (is != null ) {
                    try {
                        is.close();
                   }
                    catch (IOException e) {
                        e.printStackTrace();
                   }
              }
          }
           return class1;
     }
      private byte [] getClassFileBytes(String classFile) throws Exception {
          FileInputStream fis = new FileInputStream(classFile);
          FileChannel fileC = fis.getChannel();
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          WritableByteChannel outC = Channels.newChannel(baos);
          ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
           while ( true ) {
               int i = fileC.read(buffer);
               if (i == 0 || i == -1) {
                    break ;
              }
              buffer.flip();
              outC.write(buffer);
              buffer.clear();
          }
          fis.close();
           return baos.toByteArray();
     }
      public static void main(String[] args) {
          String ext = "java.ext.dirs" ;
          System. out .println( "java.ext.dirs :\n" + System.getProperty(ext));
          String cp = "java.class.path" ;
          System. out .println( "java.class.path :\n" + System.getProperty(cp));
          ClassLoader currentClassloader = ClassLoaderTest1. class .getClassLoader();
          System. out .println( "currentClassloader is " + currentClassloader);
          String pp = "E:\\eclipsenew\\workspace\\RedisTest\\bin\\" ;
          ClassLoaderTest1 cl = new ClassLoaderTest1(currentClassloader, pp);
          System. out .println();
          System. out .println();
          String name = "sms.DataBean" ;
           try {
              Class<?> loadClass = cl.loadClass(name);
              Object object = loadClass.newInstance();
              System. out .println();
              System. out .println( " invoke some method !" );
              System. out .println();
              Method method = loadClass.getMethod( "showData" );
              method.invoke(object);
          }
           catch (Exception e) {
          }
     }
}
显示结果:
java.ext.dirs :
C:\Program Files\Java\jdk1.7.0_17\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
java.class.path :
E:\eclipsenew\workspace\RedisTest\bin;。。。。。。
name:sms.DataBean
try to use ExtClassLoader to load class : sms.DataBean
ExtClassLoader.loadClass :sms.DataBean Failed
try to ClassLoaderTest1 load class : sms.DataBean
try findClass sms.DataBean
classFile:E:\eclipsenew\workspace\RedisTest\bin\sms\DataBean.class
class1 begin :null
name:sms.BaseBean
try to use ExtClassLoader to load class : sms.BaseBean
ExtClassLoader.loadClass :sms.BaseBean Failed
try to ClassLoaderTest1 load class : sms.BaseBean
try findClass sms.BaseBean
classFile:E:\eclipsenew\workspace\RedisTest\bin\sms\BaseBean.class
class1 begin :null
name:java.lang.Object
try to use ExtClassLoader to load class : java.lang.Object
real cls : class java.lang.Object
real ClassLoader : null
ExtClassLoader.loadClass :java.lang.Object Successful
real ClassLoader : null
class1 end :class sms.BaseBean
ClassLoaderTest1.loadClass :sms.BaseBean Successful
real ClassLoader : sms.ClassLoaderTest1@334021a9
class1 end :class sms.DataBean
ClassLoaderTest1.loadClass :sms.DataBean Successful
real ClassLoader : sms.ClassLoaderTest1@334021a9
 invoke some method !
name:java.lang.String
try to use ExtClassLoader to load class : java.lang.String
real cls : class java.lang.String
real ClassLoader : null
ExtClassLoader.loadClass :java.lang.String Successful
real ClassLoader : null
name:java.lang.System
try to use ExtClassLoader to load class : java.lang.System
real cls : class java.lang.System
real ClassLoader : null
ExtClassLoader.loadClass :java.lang.System Successful
real ClassLoader : null
name:java.io.PrintStream
try to use ExtClassLoader to load class : java.io.PrintStream
real cls : class java.io.PrintStream
real ClassLoader : null
ExtClassLoader.loadClass :java.io.PrintStream Successful
real ClassLoader : null
Show DataBean!

4.自定义classloader (二)
public class TestClassLoader {
      public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
          ClassLoader myLoader = new ClassLoader() {
               public Class<?> loadClass(String name) throws ClassNotFoundException {
                    try {
                        System. out .println( "name:" + name);
                         if (name.startsWith( "java" )) {
                              return super .loadClass(name);
                        }
                        String fileName = name.substring(name.lastIndexOf( "." ) + 1) + ".class" ;
                        InputStream is = getClass().getResourceAsStream(fileName);
                         if (is == null ) {
                              return super .loadClass(fileName);
                        }
                         byte [] b = new byte [is.available()];
                        is.read(b);
                         return defineClass(name, b, 0, b. length );
                   }
                    catch (IOException e) {
                         throw new ClassNotFoundException();
                   }
              }
          };
          Object obj1 = TestClassLoader. class .getClassLoader().loadClass( "sms.TestClassLoader" ).newInstance();
          System. out .println(obj1.getClass());
          System. out .println(obj1 instanceof sms.TestClassLoader);
          Object obj2 = myLoader.loadClass( "sms.TestClassLoader" ).newInstance();
          System. out .println(obj2.getClass());
          System. out .println(obj2.getClass().getClassLoader());
          System. out .println(obj2 instanceof sms.TestClassLoader);
     }
}

运行结果:
class sms.TestClassLoader
true
name:sms.TestClassLoader
name:java.lang.Object
name:java.lang.ClassLoader
name:sms.TestClassLoader$1
class sms.TestClassLoader
sms.TestClassLoader$1@6a998c1
false

最好的办法是不重写loadClass方法,而是重写findClass方法,同样可以达到目的。
这点在ClassLoader的loadClass方法的注释中有提及
 *  <p>  Subclasses of  <tt> ClassLoader </tt>  are encouraged to override  {@link
     * #findClass(String)}, rather than this method.   </p>
 
重写findClass后,代码如下:
@Override
         public  Class<?> findClass(String name)  throws  ClassNotFoundException{
                try {
                     String fileName = name.substring(name.lastIndexOf(  "." )+1) +  ".class" ;
                     InputStream is =  this .getClass().getResourceAsStream(fileName);
                       byte [] b =  new  byte [is.available()];
                     is.read(b);
                       return  defineClass(name, b, 0, b. length  );
              }  catch (IOException e){
                       throw  new  ClassNotFoundException(name);
              }
       }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值