类加载和内存区域划分
jvm什么时候会加载一个类?
- 代码中用到这个类的时候
- new对象的时候
- 加载子类,首先要加载父类
类加载过程
- 加载 外部的 .class 文件,加载到 Java 的方法区内(内存)
- 链接
- 验证 验证字节码是否符合规范
- 准备 静态变量分配内存并且设置默认值
- 解析 符号引用替换为直接引用
- 初始化 类变量赋值,执行静态代码块
类里面都有什么?
- 静态变量
- 静态代码块
- 静态方法
- 构造方法
- 实例变量
- 实例方法
- 局部变量
类加载器
- 启动类加载器 lib/rt.jar
- 扩展类加载器 lib/ext/*.jar
- 应用类加载器 classpath目录下的类 (classpath =>WEB-INF/classes目录下)
加载机制-双亲委派机制
- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父加载器去执行,如果父载器还存在其父加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载
- 好处
- 防止核心库被篡改
- 避免类的重复加载:当父ClassLoader已经加载了该类的时候,就不需要子ClassLoader再加载一次
- Tomcat打破了双亲委派机制
- Tomcat自定义了Common、Catalina、Shared等类加载器,加载Tomcat自己的一些核心基础类库
- Tomcat为每个部署在里面的Web应用都有一个对应的WebApp类加载器,负责加载我们部署的这个Web应用的类
jvm内存区域划分
- 私有
- 程序计数器
- 记录当前执行的字节码指令的行号
- 虚拟机栈
- 一个虚拟机栈对应一个线程,和线程的生命周期相同
- 入栈出栈的过程对应方法的执行过程
- 一个方法对应一个栈帧,一个方法执行的时候,压入一个栈帧,这个方法执行完,栈帧出栈
- 所有的字节码指令,都会抽象成对栈的入栈出栈操作
- 栈帧 对应着方法
- 局部变量表
- 操作数栈 对应着方法的执行
- 动态连接
- 返回地址
- 本地方法栈
- 和虚拟机栈功能类似
- 程序计数器
- 公共
- 方法区
- 1.8之前,用永久代来实现方法区;1.8之后,用元空间来实现方法区。永久代和元空间都是方法区的实现,方法区是标准,永久代/元空间是实现
- 存放类信息
- 堆
- 存放对象
- 方法区