JVM核心机制_深入类加载器JAVA220-223

来源:互联网 发布:哈佛计算机编程课程 编辑:程序博客网 时间:2024/05/22 04:58

来源:http://www.bjsxt.com/
一、S02E220_01JVM核心机制_深入类加载器、层次结构(三种类加载器)、代理加载模式、双亲委派机制

深入类加载器

类加载器的作用
类加载器的作用

java.lang.ClassLoader类介绍
java.class.ClassLoader类介绍

类加载器的层次结构(树状结构)
类加载器的层次结构(树状结构)

类加载器的代理模式
类加载器的代理模式

java.lang.ClassLoader类API详细介绍
java.lang.ClassLoader类API详细介绍

System.out.println(ClassLoader.getSystemClassLoader());System.out.println(ClassLoader.getSystemClassLoader().getParent());System.out.println(ClassLoader.getSystemClassLoader().getParent().getParent());System.out.println(System.getProperty("java.class.path"));

二、S02E221_01JVM核心机制_深入类加载器、自定义文件系统类加载器、网络自定义类加载器

自定义类加载器

package com.test.classloader;/** * 测试自定义的FileSystemClassLoader */public class Demo02 {    public static void main(String[] args) throws Exception {        FileSystemClassLoader loader = new FileSystemClassLoader("g:/java/test");        FileSystemClassLoader loader2 = new FileSystemClassLoader("g:/java/test");        Class<?> c = loader.loadClass("com.test.helloworld.HelloWorld");        Class<?> c2 = loader.loadClass("com.test.helloworld.HelloWorld");        Class<?> c3 = loader2.loadClass("com.test.helloworld.HelloWorld");        Class<?> c4 = loader2.loadClass("java.lang.String");        Class<?> c5 = loader2.loadClass("com.test.classloader.Demo02");        System.out.println(c.hashCode());        System.out.println(c2.hashCode());//同一加载器加载同一个类的Class对象相同        System.out.println(c3.hashCode());//不同加载器加载同一个类,JVM认为也是不相同的类        System.out.println(c4.hashCode());        System.out.println(c4.getClassLoader());//引导类加载器        System.out.println(c3.getClassLoader());//自定义的类加载器        System.out.println(c5.getClassLoader());//系统默认的类加载器    }}
package com.test.classloader;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;/** * 自定义文件系统类加载器 */public class FileSystemClassLoader extends ClassLoader {    //com.test.helloworld  -->>  g:/java/test   com/test/HelloWorld.class    private String rootDir;    public FileSystemClassLoader(String rootDir){        this.rootDir = rootDir;    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        Class<?> c = findLoadedClass(name);        //应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类        if(null!=c){            return c;        }else{            ClassLoader parent = this.getParent();            try {                c = parent.loadClass(name);//委派给父类加载            } catch (Exception e) {                //e.printStackTrace();            }            if(null!=c){                return c;            }else{                byte[] classData = getClassData(name);                if(null==classData){                    throw new ClassNotFoundException();                }else {                    c = defineClass(name, classData, 0, classData.length);                }            }        }        return c;    }    private byte[] getClassData(String className){        String path = rootDir + "/" + className.replace(".", "/") + ".class";        //Apache工具:IOUtils,可以使用它将流中的数据转成字节数组。此处不使用        InputStream is = null;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        try {            is = new FileInputStream(path);            byte[] buffer = new byte[1024];            int temp = 0;            while( (temp=is.read(buffer)) != -1 ){                baos.write(buffer,0,temp);            }            return baos.toByteArray();        } catch (Exception e) {            e.printStackTrace();            return null;        } finally {            if(null!=is){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(null!=baos){                try {                    baos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

控制台输出

658586165858612625313833121026nullcom.test.classloader.FileSystemClassLoader@25154fsun.misc.Launcher$AppClassLoader@1d16e93

自定义网络类加载器

package com.test.classloader;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.URL;/** * 自定义网络类加载器 */public class NetClassLoader extends ClassLoader {    //com.test.helloworld  -->>  www.test.com/java/test/   com/test/HelloWorld.class    private String rootUrl;    public NetClassLoader(String rootUrl){        this.rootUrl = rootUrl;    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        Class<?> c = findLoadedClass(name);        //应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类        if(null!=c){            return c;        }else{            ClassLoader parent = this.getParent();            try {                c = parent.loadClass(name);//委派给父类加载            } catch (Exception e) {                //e.printStackTrace();            }            if(null!=c){                return c;            }else{                byte[] classData = getClassData(name);                if(null==classData){                    throw new ClassNotFoundException();                }else {                    c = defineClass(name, classData, 0, classData.length);                }            }        }        return c;    }    private byte[] getClassData(String className){        String path = rootUrl + "/" + className.replace(".", "/") + ".class";        //Apache工具:IOUtils,可以使用它将流中的数据转成字节数组。此处不使用        InputStream is = null;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        try {            URL url = new URL(path);            is = url.openStream();            byte[] buffer = new byte[1024];            int temp = 0;            while( (temp=is.read(buffer)) != -1 ){                baos.write(buffer,0,temp);            }            return baos.toByteArray();        } catch (Exception e) {            e.printStackTrace();            return null;        } finally {            if(null!=is){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(null!=baos){                try {                    baos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

三、S02E222_01JVM核心机制_深入类加载器、自定义加密解密类加载器

package com.test.classloader;/** * 测试简单加密解密(取反)操作 */public class Demo03 {    public static void main(String[] args) throws Exception {        //测试取反操作//      int a = 3;//00000011//      System.out.println(Integer.toBinaryString(a^0xff));        //加密后的class文件,正常的类加载器无法加载,报ClassFormatError//      FileSystemClassLoader loader = new FileSystemClassLoader("g:/java/test");//      Class<?> c = loader.loadClass("com.test.helloworld.temp.HelloWorld");//      System.out.println(c);        DecrptClassLoader loader = new DecrptClassLoader("g:/java/test/temp");        Class<?> c = loader.loadClass("HelloWorld");        System.out.println(c);    }}
package com.test.classloader;import java.io.FileInputStream;import java.io.FileOutputStream;/** * 加密工具类 */public class EncrptUtil {    public static void main(String[] args) {        //测试时,原class文件中,相关的类不要打包        encrpt("g:/java/test/HelloWorld.class", "g:/java/test/temp/HelloWorld.class");    }    public static void encrpt(String src,String dest){        FileInputStream fis = null;        FileOutputStream fos = null;        try {            fis = new FileInputStream(src);            fos = new FileOutputStream(dest);            int temp = -1;            while((temp=fis.read())!=-1){                fos.write(temp^0xff);//取反操作,相当于加密            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (fis != null) {                    fis.close();                }            } catch (Exception e) {                e.printStackTrace();            }            try {                if (fos != null) {                    fos.close();                }            } catch (Exception e) {                e.printStackTrace();            }        }    }}
package com.test.classloader;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;/** * 加载文件系统中加密后的class字节码的类加载器(解密加载) */public class DecrptClassLoader extends ClassLoader {    private String rootDir;    public DecrptClassLoader(String rootDir){        this.rootDir = rootDir;    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        Class<?> c = findLoadedClass(name);        //应该要先查询有没有加载过这个类。如果已经加载,则直接返回加载好的类。如果没有,则加载新的类        if(null!=c){            return c;        }else{            ClassLoader parent = this.getParent();            try {                c = parent.loadClass(name);//委派给父类加载            } catch (Exception e) {                //e.printStackTrace();            }            if(null!=c){                return c;            }else{                byte[] classData = getClassData(name);                if(null==classData){                    throw new ClassNotFoundException();                }else {                    c = defineClass(name, classData, 0, classData.length);                }            }        }        return c;    }    private byte[] getClassData(String className){        String path = rootDir + "/" + className.replace(".", "/") + ".class";        //Apache工具:IOUtils,可以使用它将流中的数据转成字节数组。此处不使用        InputStream is = null;        ByteArrayOutputStream baos = new ByteArrayOutputStream();        try {            is = new FileInputStream(path);            int temp = -1;            while((temp=is.read())!=-1){                baos.write(temp^0xff);//取反操作,相当于解密            }            return baos.toByteArray();        } catch (Exception e) {            e.printStackTrace();            return null;        } finally {            if(null!=is){                try {                    is.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(null!=baos){                try {                    baos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

四、S02E223_01JVM核心机制_线程上下文类加载器、web服务器类加载机制、OSGI技术模块开发原理介绍

线程上下文类加载器
线程上下文类加载器

package com.test.classloader;/** * 线程上下文类加载器的测试 */public class Demo05 {    public static void main(String[] args) throws Exception {        ClassLoader loader = Demo05.class.getClassLoader();        System.out.println(loader);        ClassLoader loader2 = Thread.currentThread().getContextClassLoader();        System.out.println(loader2);        Thread.currentThread().setContextClassLoader(new FileSystemClassLoader("g:/java/test"));        System.out.println(Thread.currentThread().getContextClassLoader());        Class<Demo01> c = (Class<Demo01>) Thread.currentThread().getContextClassLoader().loadClass("com.test.classloader.Demo01");        System.out.println(c);        //写的时候,FileSystemClassLoader采用双亲委派机制,所以是AppClassLoader。这个可以按自己的方式修改,这里只是测试,不改了。        System.out.println(c.getClassLoader());    }}

TOMCAT服务器的类加载机制
TOMCAT服务器的类加载机制

OSGI原理介绍
OSGI原理介绍

0 0