• 一个例子深入理解ClassLoader


    文件类加载器,该加载器重载了loadClass方法,逻辑是只读取文件来加载类,不委托给父类加载器进行加载

    package com.ydd.study.hello.classloader;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class FileSystemClassLoader extends ClassLoader {
        private String rootDir; 
    
        public FileSystemClassLoader(String rootDir) { 
            this.rootDir = rootDir; 
        } 
    
        protected Class<?> findClass(String name) throws ClassNotFoundException { 
            byte[] classData = getClassData(name); 
            if (classData == null) { 
                throw new ClassNotFoundException(); 
            } 
            else { 
                return defineClass(name, classData, 0, classData.length); 
            } 
        } 
        @Override
        public Class<?> loadClass(String name)
        {
            try {
                return  findClass(name);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return null;
            }
            
            
        }
    
        private byte[] getClassData(String className) { 
            String path = classNameToPath(className); 
            try { 
                InputStream ins = new FileInputStream(path); 
                ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
                int bufferSize = 4096; 
                byte[] buffer = new byte[bufferSize]; 
                int bytesNumRead = 0; 
                while ((bytesNumRead = ins.read(buffer)) != -1) { 
                    baos.write(buffer, 0, bytesNumRead); 
                } 
                return baos.toByteArray(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
            return null; 
        } 
    
        private String classNameToPath(String className) { 
            return rootDir + File.separatorChar 
                    + className.replace('.', File.separatorChar) + ".class"; 
        } 
    }

    测试代码

    package com.ydd.study.hello.classloader;
    
    import org.junit.Test;
    
    
    public class FileSystemClassLoaderTest   {
        @Test
        public void test()
        {
            FileSystemClassLoader fileSystemClassLoader=new FileSystemClassLoader("D:\");
            try {
                Class<?>c=fileSystemClassLoader.loadClass("TestClass");
                System.out.println(c);
                Object testClass=(c.newInstance());
                System.out.println(c+"|"+testClass);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }

    从下面的输出,可以看出:

    1、在加载TestClass类时就已经引起其他类的加载了。

    2、不要轻易重载loadClass(),双亲制很重要,否则会引起一个类存在多个Class对象。

    3、类A依赖的其他类的加载,全部都是由类A的ClassLoader进行初始发起加载

    java.io.FileNotFoundException: D:javalangObject.class (系统找不到指定的路径。)
    	at java.io.FileInputStream.open(Native Method)
    	at java.io.FileInputStream.<init>(FileInputStream.java:146)
    	at java.io.FileInputStream.<init>(FileInputStream.java:101)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.getClassData(FileSystemClassLoader.java:42)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.findClass(FileSystemClassLoader.java:17)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.loadClass(FileSystemClassLoader.java:29)
    	at java.lang.ClassLoader.defineClass1(Native Method)
    	at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    	at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.findClass(FileSystemClassLoader.java:22)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.loadClass(FileSystemClassLoader.java:29)
    	at com.ydd.study.hello.classloader.FileSystemClassLoaderTest.test(FileSystemClassLoaderTest.java:12)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:606)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
    java.lang.ClassNotFoundException
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.findClass(FileSystemClassLoader.java:19)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.loadClass(FileSystemClassLoader.java:29)
    	at java.lang.ClassLoader.defineClass1(Native Method)
    	at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    	at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.findClass(FileSystemClassLoader.java:22)
    	at com.ydd.study.hello.classloader.FileSystemClassLoader.loadClass(FileSystemClassLoader.java:29)
    	at com.ydd.study.hello.classloader.FileSystemClassLoaderTest.test(FileSystemClassLoaderTest.java:12)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.lang.reflect.Method.invoke(Method.java:606)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
    

      

  • 相关阅读:
    js简单错误
    angular ie.浏览器报错 “无效指针”
    angular 取路由参数进行判断
    java学习之路--I/O流
    JavaFTP文件传输上传和下载文件
    java知识库
    Android常用的工具类SharedPreferences封装类SPUtils
    java学习之路--继承(多态的动态绑定)
    java学习之路--继承(子类构造器)
    java核心技术笔记
  • 原文地址:https://www.cnblogs.com/YDDMAX/p/5484131.html
Copyright © 2020-2023  润新知