JVM内存分区:五大区
1.Java堆:几乎所有的对象实例和数组都在这类分配内存
2.方法区:它用于存储已经被虚拟机加载的类信息(static)、常量、静态变量、即时编译器编译后的代码等数据
3.虚拟机栈:用于存储局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息
4.本地方法栈: 该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为使用到的本地操作系统方法服务
5.程序计数器:它是当前线程所执行的字节码的行号指示器
加载流程
1.加载:类加载器把编译好的class文件加载到jvm内存中
把静态变量转变为方法区的数据结构
在java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口
2.验证:验证class文件格式数据是否正确
3.准备(不执行代码):为静态变量赋默认值,分配内存空间
4.解析:将常量池中的符号引用转化为直接引用
5.初始化(执行代码):
先运行静态变量和静态代码块
调用普通方法和构造器,如果父类未初始化则先初始化父类
主动调用:
1.new实例
2.调用反射
3.对static属性赋值
被动调用:
初始化并未用到该类
类加载器详解
双亲委派模型。双亲委派模型要求除了顶层的启动类加载器,其余的类加载器都应该有自己的父类加载器。这里类加载器之间的父子关系一般不会以继承关系来实现,而是使用组合关系来复用父加载器的代码。
双亲委派模型的工作过程是:如果一个类加载器收到了类加载器的请求,它首先不会自己尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类时),子加载类才会尝试自己去加载。