JAVA基础知识|java虚拟机(JVM)

时间:2021-11-27 10:27:22

一、JVM简介

java语言是跨平台的,兼容各种操作系统。实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库;jdk=jre+开发工具)。

1.1、JVM体系结构

主要分为:类装载器(ClassLoader)子系统、运行时数据区和执行引擎。

  • 类加载器:在JVM启动时或者类在运行时将需要的class加载到JVM中
  • 执行引擎:负责执行class文件中的字节码指令,相当于CPU
  • 运行时数据区:将内存划分成若干个区,分别完成不同的任务

1.2、JVM生命周期

  • 启动:启动一个Java程序时,一个JVM实例就产生了,任何一个拥有public static void main(String[] args)函数的类都可以作为JVM实例运行的起点。
  • 运行:main()作为该程序初始线程的起点,任何其他线程均由该线程启动。
  • 消亡:当程序中所有非守护线程的都终止时,JVM才退出。Java中的线程分为两种:守护线程 (daemon)和普通线程(non-daemon)。守护线程是Java虚拟机自己使用的线程,比如负责垃圾收集的线程就是一个守护线程。当然,你也可以把自己的程序设置为守护线程。包含main()方法的初始线程不是守护线程。

一、JVM运行时数据区

JAVA基础知识|java虚拟机(JVM)

1.1、程序计数器

线程私有,生命周期与线程同步。记录代码执行的行数,主要目的是为了处理器在线程切换的时候,能恢复到正确位置继续执行。唯一不会出现OutOfMemoryError的区域。

1.2、虚拟机栈

线程私有,生命周期与线程同步。每个方法执行的时候,都会在栈中创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出入口等。每个方法从调用到完成,就是一个栈帧入栈到出栈的过程。

局部变量表:方法相关的局部变量,包括基本类型(int、float、double、char、bool等)、对象引用(reference)、引用地址(returnAddress )等。

两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出*Error 异常;如果虚拟机栈可以动态扩展(当前大部分的Java 虚拟机都可动态扩展,只不过Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError 异常。

1.3、本地方法栈

线程私有,与虚拟机栈的执行过程基本相同,唯一的区别就是虚拟机栈执行java方法,本地方法栈执行Native方法。当内存空间不足,会抛出OutOfMemoryError 异常。

1.4、方法区

线程共享,存储被虚拟机加载的类信息、常量(final)、静态变量(static)、即时编译后的代码。当内存空间不足,会抛出OutOfMemoryError 异常。

1.5、堆

线程共享,主要用于存储对象实例,垃圾回收器作用的主要区域。当内存空间不足,会抛出OutOfMemoryError 异常。

关于栈和堆的关系,可以参考《JAVA基础知识|堆和栈》

1.6、直接内存

不是虚拟机运行的一部分,也不是java虚拟机规范中定义的内存区域。当内存空间不足,会抛出OutOfMemoryError 异常。

二、对象访问的两种方式

了解这两种方式,目的是加深理解对象在栈、堆、方法区中的联系。

2.1、句柄访问

虚拟机栈中包含对象的句柄池地址,句柄池中包含对象的实例地址和对象类型地址(方法区中的类信息);

JAVA基础知识|java虚拟机(JVM)

2.2、直接指针访问

虚拟机栈直接指向对象实例和对象类型指针,访问速度更快。

JAVA基础知识|java虚拟机(JVM)

三、实例分析

 尝试对具体实例进行分析,有不对的地方,恳请指点。

package src;

import java.util.ArrayList;

//类信息会被存放在方法区
public class Person {

    private String name;//存放在堆中,因为该类被实例化后存放在堆中,当然也包含它的属性
    private int age;//存放在堆中
    public static String country;//存放在方法区
    public final String world = "地球";//存放在方法区

    //当方法被调用的时候,会创建一个栈帧用于存储方法中的局部变量表,方法出口等信息
    public void getMessge(String name, String age) {
        int a = 0;//存储在虚拟栈
        //arrayList 存放在虚拟栈,new ArrayList<>()存放在堆中
        ArrayList<String> arrayList = new ArrayList<>();
    }

}