深入理解JVM-类加载及类加载器 (7)

image-20200212212108254

package com.erwa.jvm; import java.io.*; public class MyTest16 extends ClassLoader { private String classLoaderName ; private final String fileExtension =".class"; //构造方法 public MyTest16(String classLoaderName){ super();// 将系统类加载器当做该类加载器的父加载器 this.classLoaderName = classLoaderName; } public MyTest16(ClassLoader parent,String classLoaderName){ super(parent);// 显示指定该类加载器的父加载器 this.classLoaderName = classLoaderName; } @Override public String toString() { return "MyTest16{" + "classLoaderName='" + classLoaderName + '\'' + ", fileExtension='" + fileExtension + '\'' + '}'; } @Override protected Class<?> findClass(String classname) throws ClassNotFoundException { // 重写findClass byte[] data = this.loadClassDate(classname); return this.defineClass(classname, data, 0, data.length); } private byte[] loadClassDate(String name){ InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null; try{ this.classLoaderName = this.classLoaderName.replace(".","http://www.likecs.com/"); is = new FileInputStream(new File(name + this.fileExtension)); baos = new ByteArrayOutputStream(); int ch = 0; while (-1 != (ch = is.read())) { baos.write(ch); } data = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); }finally { try { assert is != null; is.close(); assert baos != null; baos.close(); } catch (IOException e) { e.printStackTrace(); } } return data; } public static void test(ClassLoader classLoader) throws ClassNotFoundException, IllegalAccessException, InstantiationException { Class<?> clazz = classLoader.loadClass("com.erwa.jvm.MyTest1"); //创建类的实例 Object object = clazz.newInstance(); System.out.println(object); } public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { MyTest16 loader1 = new MyTest16("loader1"); test(loader1); } } > 输出结果: > Task :MyTest16.main() com.erwa.jvm.MyTest1@6d06d69c 定义的第一个自定义的类加载器结束。 类加载器重要方法详解

启动类加载器

扩展类加载器

应用类加载器

自定义类加载器

拒绝低效率的学习

通过defineClass,将byte转换成Class的对象。 protected final Class<?> defineClass(String name, byte[] b, int off, int len){}

image-20200209150126348

image-20200209142333383

案例结果如下:

image-20200209142624312

类加载器的命名空间

image-20200212211744291

每个类加载器都有 自己的命名空间,命名空间由该加载器及所有父加载器所加载的类组成

子加载器所加载的类能够访问父加载器所加载的类

父加载器加载的类无法访问子加载器所加载的类

在同一个命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类

在不同的命名空间中,有可能会出现类的完整名字(包括类的包名)相同的两个类

image-20200209143258500

输出结果一样,说明loader1 和loader2成为了父子关系,在同一命名空间中。

image-20200209144439558

image-20200209144532735

不同类加载器的命名空间关系

image-20200212173018051

类的卸载

image-20200209144847859

image-20200209144920023

image-20200209145030174

类的卸载举例:

image-20200209145335522

image-20200209145532976

也可以通过一个小工具,来查看 jvisualvm

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszsp.html