【图灵干货】Jvm如何加载类?如何分配空间?
2021-12-14 11:37:14
java基础JVM如何加载类?如何分配空间?指将class文件的二进制数据读入运行时的数据区(JVM在内存中划分),在方法区创建class对象JVM运行时划分内存空间,称为运行时的数据区。
运行时,数据区分为以下几部分:
1.栈:
当每个线程运行时,它将对应于一个堆栈(线程堆栈)。堆栈中存储的数据由当前线程独享,不会产生资源共享,因此线程是安全的。
堆栈中存储着堆栈帧。当线程调用方法时,形成堆栈帧并压制堆栈。方法实施后,进行堆栈操作。堆栈帧包括局部变量、操作数堆栈、指向当前方法对应的常量池引用、方法返回地址等信息。
2.本地方法栈:
本地方法栈的机制与栈相似,区别在于栈运行Java实现方法,本地方法栈运行本地方法。本地方法是指JVM需要调用非Java语言的方法,如C语言。在JVM规范中,没有强化要求实现者必须划分本地方法栈(例如,HotSpot虚拟机将本地方法栈和栈结合起来)和具体实现(不同的操作系统对JVM规范有不同的具体实现)。
3.程序计数器:
程序计数器也可以称为PC寄存器(通常是指令缓存)。它主要用于缓存当前程序下一个指令的指令地址,CPU根据该地址找到要执行的指令。该寄存器在JVM内部实现,而不是物理概念计数器,但与JVM的实现逻辑相同。
4.堆:
堆内存主要存储创建的对象和数组。堆内存是JVM中唯一的,可以通过多个线程共享。堆中的每个对象都存储实例变量。如果不引用堆内存对象,Java垃圾回收机制将自动回收堆内存对象。
当局部变量在方法中定义时,如果该变量是基本的数据类型,则该变量值直接存储在栈中;如果该变量是引用数据类型,则该变量值存储在堆内存中,堆内存储指向堆中的引用地址。
5.方法区:
JVM中的方法区也是一个非常重要的内存区域,像堆一样,可以多个线程共享。
主要存储每个加载class的信息。class信息主要包括魔数(确定是否为class文件)、常量池、访问标志(当前类是普通类还是接口,是抽象类,是否用public修改,是否使用final修改等描述信息...)、字段表集合信息(使用什么访问修改符,是实例变量还是静态变量,是否使用final修改等描述信息...)、方法表集合信息(使用什么访问修改符,是否静态,是否使用final修改,是否使用synchronized修改,是否使用native方法...)等。当一个类加载器加载一个类时,它将根据这个class文件创建一个class对象,包含上述信息。
根据这个class对象创建这类实例。
6.常量池:
常量池是方法区的一部分,存储class对象中最重要的资源。JVM为每个class对象维护一个常量池。