java内存分布
要想搞懂一个了类如何加载到内存,先要搞懂JVM的内存使用方法,JVM的内存划分可以分为三大块。
- 栈(stack):连续的空间,先进后出,存放局部变量
- 堆(heap):不连续的空间,用于存在new 出来的对象
- 方法区(在堆中):用于存放 ①代码 ②静态变量 ③静态方法 ④常量池 (即存储**类(Class)**本身的信息)
大致划分如下图所示:
类加载过程
分为三大步骤
- 加载
- 链接
- 初始化
一.加载
将编译器编译完成的.class文件读入JVM(java virtual machine)虚拟机,将静态的文件转换成方法区的数据结构,之后再堆中生成一个java.lang.Class对象(每个类都只有一个的类对象)(tips:new出来的对象也放在堆中)
二.链接
1.验证加载了信息符合JVM规范
2.为类中static变量分配初始值(java八种数据类型的初始值各不相同),这些内存都将在方法区中分配
3.解析,将符号引用替换为直接引用(这块不明白2021年1月18日10:48:57)
三.初始化
1.执行类构造器(注意:不是对象)()语句,执行所有的static语句,演示代码如下所示。
2.当初始化一个类的,它的父类还未初始化,则先初始化父类(意思是先加载父类的static代码块)
3. 在多线程任务中加锁
package com.earth.learning;
public class ClassLoaderTest {
public static void main(String[] args) {
Student student = new Student();
System.out.println(Student.m);
}
}
class Person{
static {
System.out.println("父类代码初始化。。");
}
}
class Student extendes Person{
static int m=200;
public Student(){
System.out.println("默认构造器加载中");
System.out.println(m);
System.out.println("························");
}
static {
m=100;
System.out.println("静态代码块加载中");
m=500;
}
public static void method(){
System.out.println("这是静态方法");
}
}
执行()的语句为
<clinit>(){
int m=200;
m=100;
System.out.println("静态代码块加载中");
m=500;
}
new的时候还会调用对象构造器
最后打印的完整输出结果为
父类代码初始化。。
静态代码块加载中
默认构造器加载中
500
························
500