1.两个 ClassLoaderTest.class 在静态方法以及 方法中定义了不一样的打印,用于区分。 2.自定义一个 自定义的class类加载器 ( myLoader ),加载的是不在classPath(编译器目录下)下的,class类(ClassLoaderTest.class)
3.分别用自定义类加载器初始化类,和Class.forName初始化类;
package org.dragsun;
/**
* Created by zhuangjiesen on 2017/7/25.
*/
public class ClassLoaderTest {
//这是自定义classLoader要加载的类
static {
System.out.println("i am new ClassLoaderTest....");
}
public static void showData(){
System.out.println("jason...hello ...");
}
}
package org.dragsun;
/**
* Created by zhuangjiesen on 2017/7/25.
*/
public class ClassLoaderTest {
//区分这是用class.forName加载的
static {
System.out.println("i am old.......111111 ClassLoaderTest....");
}
public static void showData(){
System.out.println("jason...hello ...");
}
}
1.自定义的外部的类加载
public static void main(String[] args) throws Exception {
/*
定义了自定义的类加载器,并打破父类委托机制,调用defineClass 自己加载类,所以加载类的加载器不是AppClassLoader
*
* */
ClassLoader myLoader = new ClassLoader() {
@Override
public Class> loadClass(String name) throws ClassNotFoundException {
try {
if (name.startsWith("org.dragsun")) {
File classLoaderTestClassFile = new File("/Users/zhuangjiesen/develop/java/ClassLoaderTest.class");
FileInputStream fins = new FileInputStream(classLoaderTestClassFile);
byte[] b = new byte[fins.available()];
fins.read(b);
return defineClass(name , b , 0 , b.length);
}
} catch (Exception e) {
e.printStackTrace();
}
return super.loadClass(name);
}
};
Class classLoaderTest = myLoader.loadClass("org.dragsun.ClassLoaderTest");
//通过实例化加载类 classLoaderTest.newInstance(); Class.forName("org.dragsun.ClassLoaderTest");
}
i am new ClassLoaderTest....
i am old.......111111 ClassLoaderTest....
说明两个类并不是同一个类 但是虚拟机可以存在两个全限定名一样的类,并且都可以进行实例化,各自运行;
@CallerSensitive
public static Class> forName(String className)
throws ClassNotFoundException {
/*
发现这里的 forName0 方法中居然传了个classLoader 进来,说明class.forName方法也是需要一个类加载器的
*/
Class> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
发现caller 的类加载器就是Launcher$AppClassLoader 类(应用程序类加载器,系统默认加载器)
/*
name 是全限定名
initialize 是是否初始化,如果false 只会对类进行加载 , 不触发 方法
loader 也就是可以自定义类加载器
*/
public static Class> forName(String name, boolean initialize,
ClassLoader loader)
public static void main(String[] args) throws Exception {
/*
定义了自定义的类加载器,并打破父类委托机制,调用defineClass 自己加载类,所以加载类的加载器不是AppClassLoader
*
* */
ClassLoader myLoader = new ClassLoader() {
@Override
public Class> loadClass(String name) throws ClassNotFoundException {
try {
if (name.startsWith("org.dragsun")) {
File classLoaderTestClassFile = new File("/Users/zhuangjiesen/develop/java/ClassLoaderTest.class");
FileInputStream fins = new FileInputStream(classLoaderTestClassFile);
byte[] b = new byte[fins.available()];
fins.read(b);
return defineClass(name , b , 0 , b.length);
}
} catch (Exception e) {
e.printStackTrace();
}
return super.loadClass(name);
}
};
Class classLoaderTest = myLoader.loadClass("org.dragsun.ClassLoaderTest");
Class.forName("org.dragsun.ClassLoaderTest" , true , myLoader);
Class.forName("org.dragsun.ClassLoaderTest");
}
i am new ClassLoaderTest....
i am old.......111111 ClassLoaderTest....
不同的类加载器可以加载不同的类,并进行操作
Class.forName 默认了系统(应用程序) 类加载器(Laucher$AppClassLoader)
被同一个虚拟机加载,只要他们的加载器不同,必定不会相同
如果没有重写loadClass 且classPath 已经有一样全限定名的类,自定义类加载器只会调用父类加载器(应用程序类加载器) 加载类