JVM作用
负责将字节码加载到内存中(运行时数据区)
负责存储数据
把字节码翻译为机器码,执行
垃圾回收
JVM组成部分
1.类加载器(负责加载字节码文件)
2.运行时数据区(存储运行时数据,堆,java虚拟机栈(运行java自己的方法),方法区,程序计数器,本地方法栈)
3.执行引擎(更加的底层,把字节码翻译为机器码)
4.本地方法接口
5.垃圾回收
类加载器
作用:负责从硬盘或者网络中加载字节码信息,加载到内存中(运行时数据区的方法中)
类加载的过程
加载:
使用io读取字节码文件
转换并存储,为每一个类创建一个Class类的对象
储存在方法区中
链接:(验证,准备,解析)
验证: 对字节码文件格式进行验证,文件是否被污染.
对基本的语法格式进行验证.
准备: 为静态的变量进行内存分配
public static int value = 123;value 在准备阶段后的初始值是 0,而不是 123
静态常量在编译期间就初始化
解析: 将符号引用转为直接引用.
将字节码中的表现形式,转为内存中表现(内存地址)
初始化
类的初始化,为类中的定义的静态变量进行赋值
public static int value = 123;value 在初始化阶段后值是 123.
类什么时候会被加载(初始化)
1.在类中运行main方法
2.创建对象
3.使用类中的静态变量,静态方法
4.反射 Class.forName("类的地址");
5.子类被加载
以下两种情况类不会被初始化:
static final int b = 20; 编译期间赋值的静态常量
System.out.println(User.b);
User[] users = new User[10]; 作为数组类型
类加载器
具体的负责加载类的一些代码
1.引导类加载器,用从c/c++语言开发的,jvm底层的开发语言,负责加载java核心类库。与java语言无关。
2.扩展类加载器:java语言编写的,由 sun.misc.Launcher$ExtClassLoader 实现,继承ClassLoader类. 从 JDK 系统安装目录的 jre/lib/ext 子目录(扩展目录)下加载类库 。
3.应用程序类加载器
Java语言编写的,由sun.misc.Launcher$AppClassLoader实现,派生于ClassLoader类。
4.自定义类加载器
双亲委派机制
加载一个类时,先委托给父类加载器加载,如果父加载器没有找到,继续向上级委托,直到引导类加载器.父级找到就返回,父级如果最终没有找到,就委派给子级加载器,最终没有找到,报ClassNotFoundException再向下一层层寻找,为了确保先加载系统类
双亲委派机制,是java提供的类加载的规范,但不是强制不能改变的.
我们可以通过自定义的类加载器,改变加载方式.
打破双亲委派机制
可以通过继承ClassLoader类,重写loadClass/findClass方法,实现自定义的类加载
典型的tomcat中,加载部署在tomcat中的项目时,就使用的是自己的类加载器
运行时数据区
1.程序计数器
是一块很小的内存空间,用来记录每个线程运行的指令位置,是线程私有的,每个线程都拥有一个程序计数器,生命周期与线程一致是运行时数据区中,唯一一个不会出现内存溢出的空间,运行速度最快.