类加载子系统
一.内存结构简述
内存结构简图:
运行简述:
首先是把class文件加载到内存中(使用的是类加载子系统),
然后生成大的class的对象,将必要的静态属性的进行初始化(是在方法区这块进行的)
本地方法栈主要是在调用本地的类库是使用的比如调用本地C的类库
详细图:
英文版:
中文版:
通过类加载子系统解析class文件,获取类的信息,常量,变量信息,方法的指令等,使之有组织的分配到内存之中
执行引擎需要逐条的去解释指令
二.类加载器与类的加载过程
简述:
类加载器子系统作用:
类加载器ClassLoader角色:
类的加载过程:
加载过程详情:
加载:
补充: 加载.class文件的方式
链接:
初始化:
示例1:
进行反编译之后
示例2:
示例3:
一个类只会被加载一次
三.类加载器分类
public class ClassLoaderTest {
public static void main(String[] args) {
// 获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);// sun.misc.Launcher$AppClassLoader@18b4aac2
// 获取上层: 扩展类加载器
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println(extClassLoader);// sun.misc.Launcher$ExtClassLoader@1540e19d
// 获取其上层: 获取不到引导类加载器
ClassLoader bootstrapClassLoader = extClassLoader.getParent();
System.out.println(bootstrapClassLoader);// null
// 对于用户自定义来说: 默认使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);// sun.misc.Launcher$AppClassLoader@18b4aac2
// String类使用引导类加载器加载类加载的 ---> Java的核心类库都是使用引导类加载器进行加载的
ClassLoader classLoader1 = String.class.getClassLoader();
System.out.println(classLoader1);// null
}
}
虚拟机自带的加载器:
引导类加载器: Bootstrap ClassLoader
扩展类加载器: Extension ClassLoader
应用程序类加载器(系统类加载器) : AppClassLoader
public class ClassLoaderTest1 {
public static void main(String[] args) {
System.out.println("========启动类加载器========");
// 获取BootstrapClassLoader能够加载的api的路径
URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
for (URL element : urLs) {
System.out.println(element.toExternalForm());
}
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/resources.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/rt.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/sunrsasign.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jsse.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jce.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/charsets.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/lib/jfr.jar
// file:/C:/Program%20Files/Java/jdk1.8.0_131/jre/classes
// 从上面的路径中随意选择一个类,来看看他的类加载器是什么: 引导类加载器
ClassLoader classLoader = Provider.class.getClassLoader();
System.out.println(classLoader);// null
System.out.println("========扩展类加载器========");
String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}
// C:\Program Files\Java\jdk1.8.0_131\jre\lib\ext
// C:\Windows\Sun\Java\lib\ext
// 从上面的路径中随意选择一个类,来看看他的类加载器是什么:
ClassLoader classLoader2 = CurveDB.class.getClassLoader();
System.out.println(classLoader2);// sun.misc.Launcher$ExtClassLoader@29453f44
}
}
用户自定义类加载器:
示例
public class CustomClassLoader extends ClassLoader{
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] result = getClassFromCustompath(name);
if (result == null) {
throw new FileNotFoundException();
}else {
return defineClass(name, result, 0, result.length);
}
}catch (FileNotFoundException e) {
e.printStackTrace();
}
throw new ClassNotFoundException();
}
private byte[] getClassFromCustompath(String name) {
// 从自定义路径中加载指定类
// 如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作
// .....
return null;
}
public static void main(String[] args) {
CustomClassLoader customClassLoader = new CustomClassLoader();
try {
Class<?> clazz = Class.forName("One", true, customClassLoader);
Object obj = clazz.newInstance();
System.out.println(obj.getClass().getClassLoader());
}catch (Exception e) {
e.printStackTrace();
}
}
}
关于ClassLoader
继承关系:
获取ClassLoader的途径
四.双亲委派机制
工作原理:
例子1:
例子2:
JDBC的接口是由核心类加载器进行加载的, 而在JDBC.jar中的实现类是由当前线程上下文类加载器(系统内加载器)进行加载的