目录
在讲java创建之前,我们先来了解下Java虚拟机内存组成,当Java虚拟机启动后,会将系统分配给JVM的空间逻辑上划分为堆、虚拟机栈、本地方法栈、方法区、程序计数器五个部分,如下图所示:
堆:放置new出来的对象、数组
虚拟机栈:线程运行前,会给其分配一个线程栈空间,线程中每个方法执行都会生成一个栈帧放入线程栈中,栈帧里面包含局部变量表、操作数栈、动态连接和方法出口四部分。
局部变量表:存储方法中的局部变量
操作数栈:用于赋值或者计算的数据
动态链接:方法执行的入口地址
方法出口:返回调用方法的地址
本地方法栈:与虚拟机栈类似,是调用非java方法的栈
方法区:存储类元信息、常量池
程序计数器:指向线程正在运行的位置
2 Java对象创建
new一个对象的过程如上图所示,依次执行类加载检查、分配内存、初始化零值、设置对象头和执行clinit五步。上述五步的作用分别如下:
类加载检查:检查对象对应的class文件是否已被加载
分配内存:在堆上或栈上分配内存存储对象
初始化零值:将分配的内存赋零值
设置对象头:在对象头中设置对象运行相关信息、类指针、数组长度(是数组才有)
执行clinit:赋值并执行构造函数
下面我们来详细分析下每一步里面都分别做了什么。
2.1 类加载检查
创建一个对象之前,肯定需要知道该对象对应类的相关信息,比如内存要分配多少、对象属性赋值为多少。这些信息都存储在编译后的class文件中,所以首先需要将对象的class文件加载进JVM内存,当创建该类的对象时,需要什么信息就去对应内存中获取。把class文件加载进内存的过程叫做JVM类加载,其中就涉及两个问题,第一是谁来加载,第二是具体如何加载。下面我们就来理下这两个问题。
2.1.1 谁来加载
这就要从运行java程序开始讲了,现有MyMath.class,执行java MyMath后,大体过程如下图所示。
执行java MyMath后,java.exe会调用底层jvm.dll创建Java虚拟机和引导类加载器实例,然后底层C++代码会调用Java代码创建JVM启动器实例Launcher,其中会创建扩展类加载器和应用类加载器,在创建这两个类加载器时,会将扩展类加载器的父加载器赋值为引导类加载器(实际赋值为null,引导类加载器是在C++底层生成的,JVM里面获取不到),应