JVM-4-JVM类加载器总结及自定义类加载器

来源:互联网 发布:中国旅游服务贸易数据 编辑:程序博客网 时间:2024/05/18 14:15

一、JVM类加载器总结

1.1、总结1


1.2、总结2(类加载器之间的父子关系和管辖范围图) 


二、自定义类加载器


2.1、自定义类加载器测试结果

2.1.1、情况1:
(0x,1x,2y,3y)(数字代表路径,x,表示路径下存在*.class文件,反之,y表示不存在)
直接执行java MyClassLoaderTest,报错


loader2下有*.class,loader2的父加载器都加载不了,不应该由load2来加载吗?为什么这个地方报错还是由loader1来加载?

2.1.2、情况2:

在情况1下,可通过命令 java -cp .;D:\myapp\loader2 MyClassLoaderTest运行,指定了classpath,在指定classpath路径下,AppClassLoader加载了*.class文件。


2.1.3、情况3:
(0x,1y,2x,3y)
执行命令 java MyClassLoaderTest,load1路径下存在*.class文件,则类加载器是MyClassLoader1。

2.1.4、情况4:

0中只有Dog.class,1Person.class和Dog.class2中没有,3中有Person.class和Dog.class(把Dog.class往0中拷贝了一份,即Dog.class往CLASSPATH下也放一份

执行命令 java MyClassLoaderTest。


2.2、测试代码

src/MyClassLoader.java

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;// 自定义类加载器,继承ClassLoaderpublic class MyClassLoader extends ClassLoader {                        private String name; // 给MyClassLoader起个名字private String path; // 从指定路径下加载.class文件private String fileType = ".class"; // 让系统类加载器作为其父类加载器public MyClassLoader(String name) {super();this.name = name;}// 自己指定父类加载器public MyClassLoader(String name, ClassLoader parent) {super(parent);this.name = name;}// 在加载类时被ClassLoader#loadClass(*)自动调用@Override    protected Class<?> findClass(String name) throws ClassNotFoundException {    byte[] b = loadClassData(name);return this.defineClass(name, b, 0, b.length);    }// 从指定路径下文件中加载二进制文件,name: 包名+类名public byte[] loadClassData(String name) {FileInputStream fis = null;ByteArrayOutputStream baos = null;byte[] data = null;try {name = name.replace(".", "\\");System.out.println("path + name + fileType: " + path + name + fileType);  fis = new FileInputStream(new File(path + name + fileType));baos = new ByteArrayOutputStream();int ch = 0;  while (-1 != (ch = fis.read())) {baos.write(ch); }data = baos.toByteArray();} catch (Exception e) {e.printStackTrace();} finally {try {fis.close();baos.close();} catch (Exception e2) {}}return data;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}@Overridepublic String toString() {return "MyClassLoader [name=" + name + ", path=" + path + "]";}}
src/MyClassLoaderTest.java

// 测试自定义类加载器 public class MyClassLoaderTest {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // 系统类加载器作为myClassLoader1的父类加载器 MyClassLoader loader1 = new MyClassLoader("MyClassLoader1"); loader1.setPath("D:\\myapp\\loader1\\");    // myClassLoader1作为myClassLoader2的父类加载器 MyClassLoader loader2 = new MyClassLoader("MyClassLoader2", loader1); loader2.setPath("D:\\myapp\\loader2\\");       // 根类加载器作为其父类加载器 MyClassLoader loader3 = new MyClassLoader("MyClassLoader3", null); loader3.setPath("D:\\myapp\\loader3\\");                                              System.out.println("------------load(loader2): "); load(loader2);   System.out.println("------------load(loader3): "); load(loader3);  }   private static void load(ClassLoader loader) throws ClassNotFoundException, InstantiationException, IllegalAccessException  { System.out.println("load(loader): " + loader); Class<?> clazz = loader.loadClass("jvm.demo2.Person");   Object newInstance = clazz.newInstance();      }         }
src/jvm/demo2/Person.java
package jvm.demo2;public class Person {public Person() {System.out.println("Person's classLoader is: " + this.getClass().getClassLoader());new Dog(); // 类Person主动使用类Dog } }
src/jvm/demo2/Dog.java
package jvm.demo2;public class Dog {public Dog() {System.out.println("Dog's classLoader is: " + this.getClass().getClassLoader());}       }   
2.3、目录放置情况



0 0
原创粉丝点击