Java虚拟机栈:
每个方法在被调用时就会创建一个栈帧,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
Java堆:
是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,对象实例在这里分配内存。是垃圾收集器(GC)管理的主要区域。
方法区:
存储已被虚拟机加载的类信息(如:父类,各种引用等)、常量、静态变量、即时编译器编译后的代码等数据,运行时常量池(Runtime Constant Pool)是方法区的一部分。
直接内存:
直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。
在jvm启动的时候,类的生命周期:
加载,验证,准备,解析,初始化阶段。
指的是:将类的.class文件中的二进制数据读入到内存中,将其放入到运行时数据区的方法区,然后在堆区创建一个class对象,用来封装方法区的数据结构。类加载的最终产品是堆区中的class对象,class对象封装了类在方法区的数据结构。
-
什么是类的加载:
-
类的生命周期:
完成三件事情:(加载阶段可控性最强,可以根据系统提供的类加载器完成,也可以自定义加载器完成加载)
例如:
public static int value = 3;
在准备阶段过后初始值为:0;因为没有执行任何java方法,只有程序编译后,会存放到类构造器init方法之中。
为类的静态变量赋予正确的值,jvm负责对类进行初始化,主要对类变量初始化。主要两种方式:
JVM初始化步骤:
-
加载:查找并加载类的二进制数据,为类加载过程的第一个阶段。
-
获取二进制字节流;
-
将字节流代表的静态存储结构转化为方法区的数据结构;
-
在java堆中生成一个class对象,作为方法区的数据结构的访问入口;
-
-
连接:
-
验证:确保加载类的正确性(文件格式验证,元数据验证(java语言规范等,是否有除了object以外的父类),字节码验证,符号引用验证)
-
准备:为静态变量分配内存(方法区中),并初始化默认值
-
只为static修饰的变量分配,而实例变量,只能跟随对象实例化的时候分配到java堆中。
-
初始值通常情况下是数据类型默认的零值(如:0,0L,null,false),并不是java代码中显示赋予的值。
-
-
虚拟机将常量池中的符号引用替换为直接引用:
-
解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。符号引用就是一组符号来描述目标,可以是任何字面量。
-
-
-
初始化:
-
声明类变量是指定初始值
-
使用静态代码块
-
假如这个类还没有被加载和连接,则程序先加载并连接该类
-
假如该类的直接父类还没有被初始化,则先初始化其直接父类
-
假如类中有初始化语句,则系统依次执行这些初始化语句
-
-
类加载器可以大致划分为以下三类:
Bootstrap ClassLoader,负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录,下同)下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。
Extension ClassLoader,该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载JDK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.开头的类),开发者可以直接使用扩展类加载器。
Application ClassLoader,该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
双亲委托模型:
-
启动类加载器:加载jre\lib
-
扩展类加载器:jre\lib\ext
-
应用程序类加载器:加载用户路径下文件
-
-