一、类加载器ClassLoader
负责加载class文件,class文件在文件开头有特定的文件提示,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine负责。
二、类加载顺序
2.1 Bootstrap ClassLoader
- 启动类加载器(C++)
- 用来预先加载jre下的类库,这些类都是预先载入好的
- 加载 %JAVA_HOME%/jre/lib/rt.jar 里的class
2.2 Extensioin ClassLoader
- 扩展类加载器(Java)
- 用来载入ext下的类库,也是预先载入好的
- 加载%JAVA_HOME%/jre/lib/ext/*.jar 里的class
2.3 Application ClassLoader
- 应用程序类加载器(Java)
- 用来载入当前应用工程的classes以及lib下的类库,仅仅声明,并不会载入,等到使用时才载入
- 加载$CLASSPATH 里的class
2.4 自定义 ClassLoader
自定义ClassLoad可以根据自己指定,加载哪些类。
三、类加载器-双亲委派模型+沙箱机制
3.1 双亲委派模型工作原理
1、当Application ClassLoader 收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extensioin ClassLoader去完成。
2、当Extensioin ClassLoader收到一个类加载请求时,他首先不会自己尝试去加载这个类,而是将请求委派给父类加载器 Bootstrap ClassLoader去完成。
3、当 Bootstrap ClassLoader加载失败(在<JAVA_HOE\lib中未找到所需类>),就会让Extensioin ClassLoader尝试加载。
4、如果Extensioin ClassLoader也加载失败,就会使用Application ClassLoader加载。
5、如果Application ClassLoader也加载失败,就会使用自定义加载器去尝试加载。
6、如果均加载失败,就会抛出ClassNotFoundException异常。
3.2 双亲委派模型工作过程
1、实现双亲委派模型的代码都集中在java.lang.ClassLoader的loadClass()方法中
2、首先会检查请求加载的类是否已被加载过
3、若没有被加载过
4、递归调用父类加载器的loadClass()
5、父类加载器为空后就使用启动类加载器加载
6、如果父类加载器和启动类加载器均无法加载请求,则调用自身的加载功能
3.3 双亲委派模型的优点
1、Java类伴随其类加载器具备了带有优先级的层次关系,确保了在各种加载环境的加载顺序。
2、保证了运行的安全性,防止不可信类扮演可信任的类(比如自己重写一个String类)
四、用代码模拟出StackOverflowError、OutOfMemoryError异常
public class TestClient {
public static void main(String[] args) {
// fun();
fun2();
}
/**
* 模拟出:Exception in thread "main" java.lang.StackOverflowError 异常
*/
public static void fun(){
fun();
}
/**
* 模拟出: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 异常
*/
public static void fun2(){
String str = "AlanChen";
while(true){
str+=str;
}
}
}
五、堆内存的初始值和最大值
1、-Xms 初始状态堆大小,默认为物理内存的1/64
2、-Xmx 堆的最大大小,默认为物理内存的1/4
通过以下程序可得到验证
/**
* @author Alan Chen
* @description 获取堆内存的初始值和最大值(本机电脑物理内存8G)
* @date 2020-01-13
*/
public class TestClient {
public static void main(String[] args) {
//堆内存初始值(物理内存的1/64)
long totalMemory = Runtime.getRuntime().totalMemory();
//堆内存最大值(物理内存的1/4)
long maxMemory = Runtime.getRuntime().maxMemory();
// 123MB
System.out.println("初始值:"+totalMemory/1024/1024+"MB");
// 1801MB
System.out.println("最大值:"+maxMemory/1024/1024+"MB");
}
}
六、JVM跨平台

不同系统版本的JVM将class字节码文件编码成对应系统的机器码,这样就实现了Java跨平台。
即,同一份Helloworld.class文件,发布到windows的JVM里运行,windows的JVM将Helloworld.class编码成windows机器码,就能在windows系统里运行。同样,Liunx、Mac OS版本的JVM也同理。
七、JVM组成部分

网友评论