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;
}
private byte[] loadClassData(String name){
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try {
this.classLoaderName = this.classLoaderName.replaceAll(".", "/");
is = new FileInputStream(new File(name + fileExtension));
int ch = 0;
while ((ch = is.read()) != -1){
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
is.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
return data;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
System.out.println("我执行了");
byte[] data = this.loadClassData(className);
return this.defineClass(className, data, 0, data.length);
}
@Override
public String toString() {
return "MyTest16{" +
"classLoaderName='" + classLoaderName + '\'' +
", fileExtension='" + fileExtension + '\'' +
'}';
}
public static void main(String[] args) throws Exception {
MyTest16 load1 = new MyTest16("load1");
test(load1);
}
public static void test(ClassLoader classLoader) throws Exception {
Class<?> clazz = classLoader.loadClass("main.jvm.classloader.MyTest1");
Object obj = clazz.newInstance();
System.out.println(obj);
System.out.println(obj.getClass().getClassLoader());
}
}
执行结果:
main.jvm.classloader.MyTest1@5679c6c6
sun.misc.Launcher$AppClassLoader@18b4aac2
结论:
MyTest1
是由MyTest16
的父加载器AppClassLoader
来加载public class MyTest16 extends ClassLoader {
private String classLoaderName;
private final String fileExtension = ".class";
private String path;
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
public MyTest16(String classLoaderName) {
//将系统类加载器当做该类加载器的父加载器
super();
this.classLoaderName = classLoaderName;
}
public MyTest16(ClassLoader parent, String classLoaderName) {
//显示指定该类加载器的父加载器
super(parent);
this.classLoaderName = classLoaderName;
}
private byte[] loadClassData(String className) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
className = className.replaceAll("\\.", "/");
try {
String filePath = this.path + className + fileExtension;
System.out.println("filePath="+filePath);
is = new FileInputStream(new File(filePath));
int ch = 0;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return data;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
byte[] data = this.loadClassData(className);
return this.defineClass(className, data, 0, data.length);
}
@Override
public String toString() {
return "MyTest16{" +
"classLoaderName='" + classLoaderName + '\'' +
", fileExtension='" + fileExtension + '\'' +
'}';
}
public static void main(String[] args) throws Exception {
MyTest16 load1 = new MyTest16("load1");
// load1.setPath("/Users/lutingfeng/Documents/idea/jvm_learn/out/production/jvm_learn/main/jvm/classloader");
load1.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz = load1.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz.hashCode());
Object obj = clazz.newInstance();
System.out.println(obj);
System.out.println(obj.getClass().getClassLoader());
}
}
执行结果:
clazz.hashCode=621009875
main.jvm.classloader.MyTest1@4b67cf4d
sun.misc.Launcher$AppClassLoader@135fbaa4
当删除classPath
下的MyTest1.class
文件后,执行结果:
filePath=/Users/lutingfeng/Desktop/main/jvm/classloader/MyTest1.class
clazz.hashCode=668849042
main.jvm.classloader.MyTest1@19e1023e
MyTest16{classLoaderName=‘load1’, fileExtension=’.class’}
public class MyTest16 extends ClassLoader {
private String classLoaderName;
private final String fileExtension = ".class";
private String path;
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
public MyTest16(String classLoaderName) {
//将系统类加载器当做该类加载器的父加载器
super();
this.classLoaderName = classLoaderName;
}
public MyTest16(ClassLoader parent, String classLoaderName) {
//显示指定该类加载器的父加载器
super(parent);
this.classLoaderName = classLoaderName;
}
private byte[] loadClassData(String className) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
className = className.replaceAll("\\.", "/");
try {
String filePath = this.path + className + fileExtension;
System.out.println("filePath="+filePath);
is = new FileInputStream(new File(filePath));
int ch = 0;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return data;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
byte[] data = this.loadClassData(className);
return this.defineClass(className, data, 0, data.length);
}
@Override
public String toString() {
return "MyTest16{" +
"classLoaderName='" + classLoaderName + '\'' +
", fileExtension='" + fileExtension + '\'' +
'}';
}
public static void main(String[] args) throws Exception {
MyTest16 load1 = new MyTest16("load1");
// load1.setPath("/Users/lutingfeng/Documents/idea/jvm_learn/out/production/jvm_learn/main/jvm/classloader");
load1.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz1 = load1.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz1.hashCode());
Object obj1 = clazz1.newInstance();
System.out.println(obj1);
System.out.println("classLoad="+obj1.getClass().getClassLoader());
System.out.println("----");
MyTest16 load2= new MyTest16("load2");
load2.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz2 = load2.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz2.hashCode());
Object obj2 = clazz2.newInstance();
System.out.println(obj2);
System.out.println("classLoad="+obj2.getClass().getClassLoader());
}
}
当删除classPath
下的MyTest1.class
文件后,执行结果:
filePath=/Users/lutingfeng/Desktop/main/jvm/classloader/MyTest1.class
clazz.hashCode=2125039532
main.jvm.classloader.MyTest1@12a3a380
classLoad=MyTest16{classLoaderName=‘load1’, fileExtension=’.class’}
++++
filePath=/Users/lutingfeng/Desktop/main/jvm/classloader/MyTest1.class
clazz.hashCode=1846274136
main.jvm.classloader.MyTest1@61bbe9ba
classLoad=MyTest16{classLoaderName=‘load2’, fileExtension=’.class’}
由执行结果可以看出.load1
加载的MyTest1
对应的hashCode与load2
加载的hashCode不一致,其原因是:
命名空间由该加载器及所有父加载器所加载的类组成
public class MyTest16 extends ClassLoader {
private String classLoaderName;
private final String fileExtension = ".class";
private String path;
public String getPath() {
return this.path;
}
public void setPath(String path) {
this.path = path;
}
public MyTest16(String classLoaderName) {
//将系统类加载器当做该类加载器的父加载器
super();
this.classLoaderName = classLoaderName;
}
public MyTest16(ClassLoader parent, String classLoaderName) {
//显示指定该类加载器的父加载器
super(parent);
this.classLoaderName = classLoaderName;
}
private byte[] loadClassData(String className) {
InputStream is = null;
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
className = className.replaceAll("\\.", "/");
try {
String filePath = this.path + className + fileExtension;
is = new FileInputStream(new File(filePath));
int ch = 0;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return data;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
System.out.println("findClass invoked : "+ className);
byte[] data = this.loadClassData(className);
return this.defineClass(className, data, 0, data.length);
}
@Override
public String toString() {
return "MyTest16{" +
"classLoaderName='" + classLoaderName + '\'' +
", fileExtension='" + fileExtension + '\'' +
'}';
}
public static void main(String[] args) throws Exception {
MyTest16 load1 = new MyTest16("load1");
// load1.setPath("/Users/lutingfeng/Documents/idea/jvm_learn/out/production/jvm_learn/main/jvm/classloader");
load1.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz1 = load1.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz1.hashCode());
Object obj1 = clazz1.newInstance();
System.out.println(obj1);
System.out.println("classLoad="+obj1.getClass().getClassLoader());
System.out.println("++++++++");
MyTest16 load2= new MyTest16(load1, "load2");
load2.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz2 = load2.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz2.hashCode());
Object obj2 = clazz2.newInstance();
System.out.println(obj2);
System.out.println("classLoad="+obj2.getClass().getClassLoader());
System.out.println("++++++++");
MyTest16 load3= new MyTest16(load2, "load3");
load3.setPath("/Users/lutingfeng/Desktop/");
Class<?> clazz3 = load3.loadClass("main.jvm.classloader.MyTest1");
System.out.println("clazz.hashCode="+clazz3.hashCode());
Object obj3 = clazz3.newInstance();
System.out.println(obj3);
System.out.println("classLoad="+obj3.getClass().getClassLoader());
}
}
当删除classPath
下的MyTest1.class
文件后,执行结果:
findClass invoked : main.jvm.classloader.MyTest1
clazz.hashCode=2125039532
main.jvm.classloader.MyTest1@12a3a380
classLoad=MyTest16{classLoaderName=‘load1’, fileExtension=’.class’}
++++++++
clazz.hashCode=2125039532
main.jvm.classloader.MyTest1@29453f44
classLoad=MyTest16{classLoaderName=‘load1’, fileExtension=’.class’}
++++++++
clazz.hashCode=2125039532
main.jvm.classloader.MyTest1@5cad8086
classLoad=MyTest16{classLoaderName=‘load1’, fileExtension=’.class’}