配合使用虚拟机类加载机制
一、主动使用的方式
1. 基本的主动使用方式
package club.codermax.classLoading;
import java.util.UUID;
public class Test01 {
public static void main(String[] args) {
SubClass[] sc = new SubClass[5];
System.out.println(sc.getClass());
System.out.println(sc.getClass().getSuperclass());
int[] ints = new int[5];
}
}
class SuperClass {
static {
System.out.println("SuperClass init");
}
public static int value = 123;
}
class SubClass extends SuperClass {
static {
System.out.println("SubClass init");
}
}
class ConstClass {
static {
System.out.println("ConstClass init");
}
public static final String STR = "Hello World !";
public static final int VAL1 = 6;
public static final int VAL2 = 666;
public static final int VAL3 = 5;
}
class MyTest{
public static final String STR = UUID.randomUUID().toString();
static {
System.out.println("MyTest init");
}
}
2. 对接口进行初始化
package club.codermax.classLoading;
import java.util.Random;
public class Test02 {
public static void main(String[] args) {
System.out.println(Sub.c);
}
}
interface Super{
int a = 6;
Thread thread = new Thread() {
{
System.out.println("hello Super");
}
};
}
interface Sub extends Super {
int b = 8;
int c = new Random().nextInt(2);
}
3. 验证反射对类的初始化
package club.codermax.classLoading;
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cla = Class.forName("java.lang.String");
System.out.println(cla.getClassLoader());
System.out.println("======================");
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> cl = loader.loadClass("club.codermax.classLoading.C");
System.out.println(cl);
System.out.println("======================");
Class<?> clas = Class.forName("club.codermax.classLoading.C");
System.out.println(clas.getClassLoader());
}
}
class C {
static {
System.out.println("C init");
}
}
二、双亲委托模型
1. 双亲委托模型初体验
package club.codermax.classLoading;
public class Test05 {
public static void main(String[] args) {
String[] str = new String[2];
System.out.println(str.getClass().getClassLoader());
Test05[] test05s = new Test05[2];
System.out.println(test05s.getClass().getClassLoader());
int[] ints = new int[2];
System.out.println(ints.getClass().getClassLoader());
}
}
2. 自定义类加载器
package club.codermax.classLoading;
import java.io.*;
public class Test06 extends ClassLoader{
private String classLoadName;
private String fileExtension = ".class";
private String path;
public void setPath(String path) {
this.path = path;
}
public Test06(String classLoadName) {
super();
this.classLoadName = classLoadName;
}
public Test06(ClassLoader parent, String classLoadName) {
super(parent);
this.classLoadName = classLoadName;
}
@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
System.out.println("findClass invoked: " + className);
System.out.println("classLoadName: " + this.classLoadName);
byte[] data = this.loadClassData(className);
return this.defineClass(className, data, 0, data.length);
}
private byte[] loadClassData(String className) {
InputStream in = null;
byte[] data = null;
ByteArrayOutputStream out = null;
className = className.replace(".", "\\");
try {
in = new FileInputStream(new File(this.path + className + this.fileExtension));
out = new ByteArrayOutputStream();
int oh = 0;
while ((oh = in.read()) != -1) {
out.write(oh);
}
data = out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}
public static void main(String[] args) throws Exception{
Test06 load1 = new Test06("load1");
load1.setPath("D:\\面试\\jvm\\");
Class<?> cla = load1.loadClass("club.codermax.classLoading.Test01");
System.out.println("classHashCode: " + cla.hashCode());
Object object = cla.newInstance();
System.out.println(object);
System.out.println();
Test06 load2 = new Test06(load1,"load2");
load2.setPath("D:\\面试\\jvm\\");
Class<?> cla2 = load2.loadClass("club.codermax.classLoading.Test01");
System.out.println("classHashCode: " + cla2.hashCode());
Object object2 = cla.newInstance();
System.out.println(object2);
System.out.println();
Test06 load3 = new Test06("load3");
load3.setPath("D:\\面试\\jvm\\");
Class<?> cla3 = load3.loadClass("club.codermax.classLoading.Test01");
System.out.println("classHashCode: " + cla3.hashCode());
Object object3 = cla.newInstance();
System.out.println(object3);
System.out.println();
System.gc();
}
}
三、线程上下文类加载器
1. 有关上下文类加载器的基本知识
package club.codermax.classLoading;
public class Test08 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getContextClassLoader());
System.out.println(Thread.class.getClassLoader());
}
}
2. 打破双亲委托模型的具体实现
package club.codermax.classLoading;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
public class Test10 {
public static void main(String[] args) throws Exception{
ServiceLoader<Driver> loader = ServiceLoader.load(Driver.class);
Iterator<Driver> iterator = loader.iterator();
while (iterator.hasNext()) {
Driver driver = iterator.next();
System.out.println("driver: " + driver.getClass() + ", loader: " + driver.getClass().getClassLoader());
}
System.out.println("当前线程上下文类夹杂器: " + Thread.currentThread().getContextClassLoader());
System.out.println("ServiceLoader的类加载器: " + ServiceLoader.class.getClassLoader());
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myJvmDB", "username", "password");
}
}