一、内存结构简述
内存简图:(图片来源于尚硅谷视频)
把字节码文件加载到内存中需要用到类加载器。
典型的类加载器有:引导类加载器、扩展类加载器、应用(系统)类加载器以及自定义类加载器
内存层面有运行时数据区:
PC寄存器(程序计数器),每个线程一份;
虚拟机栈,每个线程一份;
本地方法栈,跟虚拟机栈的区别就是涉及到本地方法接口API的调用;
堆,创建 Java对象主体存放在堆中,算是内存当中最大的一块空间,也是GC重点考虑的一块空间,是被多个线程共享的。
方法区,主要存放一些类的信息,常量、域、方法信息等,只有HotSpot虚拟机才有,JRockit\J9等都没有。
执行引擎:包含解释器、即时编译器、垃圾回收器,将我们的字节码指令翻译成机器指令;
手写一个虚拟机Demo的话需要两部分:类加载器子系统、执行引擎。
二、类加载器与类的加载过程
- 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件头有特定的标识。
- 类加载器(ClassLoader)只负责class文件的加载,至于是否可以运行,则由执行引擎(Execution Engine)决定。
-
加载类的信息存放在方法区。除了类的信息外,方法去还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)。
类的加载过程简单描述如下:
加载—>验证—>准备—>解析—>初始化
加载:
- 通过一个类的全限定名获取定义此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
-
在内存中
生成一个代表这个类的java.lang.Class对象
,作为方法区这个类的各种数据的访问入口
链接
验证:
- 目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
- 主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证
准备:
- 为类变量分配内存并且设置该类变量的默认初始值,即零值。
-
这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化;
-
这里不会为实例变量分配初始化,
类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
解析:
- 将常量池内的符号引用转换为直接引用的过程。
- 事实上,解析操作往往会伴随JVM在执行完初始化后再执行。
- 解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。
版权声明:本文为qq_38138791原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。