zoukankan      html  css  js  c++  java
  • java类加载器的一些测试

    package classloader;
    
    import java.lang.reflect.Method;
    
    import org.junit.Test;
    
    import com.example.Sample;
    
    
    public class ClassIdentity {
    
        public static void main(String[] args) {
            
    //        new ClassIdentity().testClassIdentity();
    //        System.out.println("执行了吗");
            
            new ClassIdentity().testICalculator();
        }
        
        public void testICalculator(){
            
            String basicClassName = "com.example.CalculatorBasic";
            String advancedClassName = "com.example.CalculatorAdvanced";
            String classDataRootPath = "C:\";
            FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
            
            try {
                Class<?> class1 = fscl1.loadClass(basicClassName);
                //下面这句会导致fscl1尝试加载在C:下面加载classloader.ICalculator
                ICalculator calculator=(ICalculator)class1.newInstance();
                System.out.println(calculator.getVersion());
                System.out.println( ICalculator.class.getClassLoader());
                System.out.println( calculator.getClass().getClassLoader());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            
        }
        @Test
        public void testClassIdentity() {
            String classDataRootPath = "C:\";
            FileSystemClassLoader fscl1 = new FileSystemClassLoader(classDataRootPath);
            FileSystemClassLoader fscl2 = new FileSystemClassLoader(classDataRootPath);
            String className = "com.example.Sample";    
            try {
                Class<?> class1 = fscl1.loadClass(className);
                Object obj1 = class1.newInstance();
    
                Class<?> class2 = fscl2.loadClass(className);
                Object obj2 = class2.newInstance();
                
                System.out.println("不同加载器->" + class1.equals(class2));
                
                Class<?> c1=  this.getClass().getClassLoader().loadClass("classloader.Versioned");
                Class<?> c2=  this.getClass().getClassLoader().loadClass("classloader.Versioned");
                
                System.out.println("同一个->" + c1.equals(c2));
                
                Method setSampleMethod = class1.getMethod("setSample", java.lang.Object.class);
    //            setSampleMethod.invoke(obj1, obj1);
    //            setSampleMethod.invoke(obj1, obj1);
                System.out.println( Sample.class.getClassLoader());
                System.out.println( ClassIdentity.class.getClassLoader());
                System.out.println(obj1.getClass().getClassLoader() );
                Sample sample=(Sample)obj1; //无法将obj1转化成Sample,引用的类加载器不同
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }
    View Code

    testICalculator()输出:
    这里com.example.CalculatorBasic
    这里classloader.ICalculator
    这里java.lang.Object
    1.0
    sun.misc.Launcher$AppClassLoader@105d88a
    classloader.FileSystemClassLoader@76fba0

    改写类加载器

    package 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);
            }
        }
    
        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";
        }
        
        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
            System.out.println("这里" + name);
            if("java.lang.Object".equals(name)
               || "classloader.ICalculator".equals(name)        
                    ){
                return super.loadClass(name, resolve);
            }
            
            return findClass(name);
        }
        
    }
    View Code

     
    注释//Sample sample=(Sample)obj1; 后的输出:
    这里com.example.Sample
    这里java.lang.Object
    这里com.example.Sample
    这里java.lang.Object
    不同加载器->false
    同一个->true
    sun.misc.Launcher$AppClassLoader@105d88a
    sun.misc.Launcher$AppClassLoader@105d88a
    classloader.FileSystemClassLoader@1866417

    打开注释后的输出:


    这里com.example.Sample
    这里java.lang.Object
    这里com.example.Sample
    这里java.lang.Object
    不同加载器->false
    同一个->true
    sun.misc.Launcher$AppClassLoader@105d88a
    sun.misc.Launcher$AppClassLoader@105d88a
    classloader.FileSystemClassLoader@1526e3
    java.lang.ClassCastException: com.example.Sample cannot be cast to com.example.Sample

  • 相关阅读:
    ChaosBlade x SkyWalking 微服务高可用实践
    工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇
    阿里 双11 同款流控降级组件 Sentinel Go 正式 GA,助力云原生服务稳稳稳
    我在阿里巴巴做 Serverless 云研发平台
    「更高更快更稳」,看阿里巴巴如何修炼容器服务「内外功」
    「云原生上云」后的聚石塔是如何应对 双11 下大规模应用挑战的
    从零入门 Serverless | SAE 的远程调试和云端联调
    利用 Arthas 解决启动 StandbyNameNode 加载 EditLog 慢的问题
    Arthas 实践——生产环境排查 CPU 飚高问题
    RocketMQ 很慢?引出了一个未解之谜
  • 原文地址:https://www.cnblogs.com/wdfrog/p/3169562.html
Copyright © 2011-2022 走看看