jvm总结来源于狂神
Posted 健身小白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvm总结来源于狂神相关的知识,希望对你有一定的参考价值。
应用程序->JVM->操作系统->硬件体系
2.JVM体系结构
Class File(字节码文件)
类加载子系统:
三个阶段:加载阶段,链接阶段,初始化阶段
加载阶段:引导类加载器,拓展类加载器,系统类加载器
链接阶段:验证,准备,解析
初始化阶段
运行时数据区:
方法栈,堆,虚拟机栈,PC寄存器,本地方法区
执行引擎:
解释器,即时编译器,垃圾回收器
即时编译器:中间代码生成器,代码优化器,目标代码生成器
程序计数器pc
字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,这下面试指令执行的顺序
99%的JVM调优都是在堆中调优,Java栈,本地方法栈,程序计数器是不会有垃圾存在的.
3.类加载器和双亲委派机制
工作原理的是,如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,即每个儿子都很懒,每次有活就丢给父亲去干,直到父亲说这件事我也干不了时,儿子自己才想办法去完成。
简单说分四步走
(1)检查是否已经被类加载器加载过(类加载器收到类加载请求)
(2)存在父加载器,递归的交由父加载器(将这个请求向上委托给父类加载器去完成,一直向上委托,知道启动类加载器)
(3)直到最上面的Bootstrap类加载器(启动类加载器检查是否能够加载当前这个类,能加载就结束就使用当前加载器,否则抛出异常,通知子加载器进行加载)
(4)重复步骤(3)
参考网上的图,结合理解
双亲委派机制是为了保证安全的,防止修改rt.jar里面的资源。
优势:避免类的重复加载和保证安全(防止核心API库被随意篡改)。
原文链接:https://blog.csdn.net/weixin_44538225/article/details/121754872
https://www.cnblogs.com/zhihaospace/p/12227726.html
类加载器
JVM自带的加载器(3种)
启动类加载器:Bootstrap ClassLoader,又名根类加载器或引导类加载器
拓展类加载器:Extension ClassLoader
系统类加载器:Application ClassLoader,又名应用类加载器
用户自定义的类加载器,一般是java.lang.ClassLoader
Java早期Java Applet需要从远程下载Java类文件到浏览器中并执行.
在java.net包中,JDK提供了一个更加易于使用的类加载器URLClassLoader,来扩展ClassLoader,能够从本地或网络上指定的位置加载类。我们可以使用该类作为自定义的类加载器使用
热部署类加载器
相同的类被同一个类加载器多次加载,则会报错。因此热部署是让同一个类文件被不同的类加载器加载重复加载即可。
我们不能调用loadClass方法,而应该调用findClass方法,避免双亲委派机制,从而实现同一个类被加载多次,实现热部署
类加载器的种类:
1-启动类加载器,负责加载%JAVA_HOME%\\bin目录下的所有jar包,或者是-Xbootclasspath参数指定的路径;
2-扩展类加载器:负责加载%JAVA_HOME%\\bin\\ext目录下的所有jar包,或者是java.ext.dirs参数指定的路径;
3-应用程序类加载器:负责加载用户类路径上所指定的类库,如果应用程序中没有自定义加载器,那么次加载器就为默认加载器。
双亲委派机制
委派机制图:
双亲委派机制的工作过程:
类加载器收到类加载的请求;
把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;
启动类加载器检查能不能加载(使用findClass()方法),能加载就结束;否则抛出异常,通知子加载器进行加载;
重复步骤三.
接下来有个狂神的示例:
package com.hua.jvmtest.test;
public class Car
public int age;
public static void main(String[] args)
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
car1.age=1;
car2.age=2;
car3.age=3;
System.out.println(car1.hashCode());
System.out.println(car2.hashCode());
System.out.println(car3.hashCode());
//都是一个模板类加载出来的
System.out.println(car1.getClass().hashCode());
System.out.println(car2.getClass().hashCode());
System.out.println(car3.getClass().hashCode());
Class<? extends Car> aClass1 = car1.getClass();
//获取类加载器
System.out.println(aClass1.getClassLoader());//AppClassLoader@18b4aac2
System.out.println(aClass1.getClassLoader().getParent());//$ExtClassLoader@2a84aee7 扩展类加载器
System.out.println(aClass1.getClassLoader().getParent().getParent());//null 说明是调不到,或者没有
//去观察jre的根加载器看rt包
//双亲委派,不允许用同包名一样的名字
package java.lang;
public class String
//错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
// public static void main(String[] args)
//否则 JavaFX 应用程序类必须扩展javafx.application.Application
//先执行根加载器,App --->exc ---Boot() 向上委托给父类加载器直到启动类加载器,如过没有就抛出异常让子类加载
//保证了安全
// 启动类加载器:Bootstrap ClassLoader,又名根类加载器或引导类加载器
// 拓展类加载器:Extension ClassLoader
// 系统类加载器:Application ClassLoader,又名应用类加载器
public String toString()
return "Hello";
public static void main(String[] args)
String s = new String();
s.toString();
new Thread().start();
// private native void start0(); 这里就是java处理不到去掉C 处理线程的 navtive(去调用本地方法库JNI)带有这个native 都执行不到
//作用:扩展java的使用,诞生的时候想去调用c 和C++
//在内存中开辟了一个区域本地方法栈 通过JNI去加载本地方法库
//java程序驱动打印机,管理系统。
栈:
递归出现栈溢出原因:一直循环入栈,然后栈中又几乎没有垃圾回收
new 一个对象会出现下面情况
以上是关于jvm总结来源于狂神的主要内容,如果未能解决你的问题,请参考以下文章