JVM基础详解

JVM概述

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
作者根据冯·诺依曼结构设计的,Java虚拟机本质上就是一个程序,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。Java语言的可移植性正是建立在Java虚拟机的基础上。任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就可以在该平台上运行。这就是“一次编译,多次运行”,因为JVM根据不同机器将字节码翻译成了不同的机器语言。

在这里插入图片描述
从官网这张图中可以看出,JVM是最低层的部分,也是JRE最核心的部分,JVM才是真正和操作系统进行交互的。

JVM组成

JVM由4大部分组成:ClassLoader(类加载器),Runtime Data Area(运行时数据区),Execution Engine(执行引擎),Java Native Interface(本地方法接口)。

1.ClassLoader(类加载器)

概述

类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM来执行类文件中的字节码来执行程序。类加载器负责加载文件系统、网络或其他来源的类文件。有三种默认使用的类加载器:Bootstrap ClassLoader类加载器、Extension ClassLoader类加载器和App ClassLoader类加载器。
在这里插入图片描述

  1. Bootstrap ClassLoader
    负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,没有父类
  2. Extension ClassLoader
    负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包,父类加载器为null
  3. App ClassLoader
    负责记载classpath中指定的jar包及目录中class,父类加载器ExtClassLoader
  4. Custom ClassLoader
    属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader,加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类,父类加载器为AppClassLoader。
2.Runtime Data Area(运行时数据区)

在这里插入图片描述
JVM运行时数据区由五个部分组成:堆(Heap),方法区(MethodArea),程序计数器(The pc Register),本地方法栈(Native Method Stacks),虚拟机栈(Java Virtual Machine Stacks)

  1. 堆(Heap):Java堆是Java虚拟机所管理内存中最大的一块,被所有线程共享(堆是JVM启动时创建,JVM启动时只有进程,与进程绑定),堆是运行时数据区域,java对象实例以及数组都在堆上分配,在堆内存之外的内存成为非堆内存。堆可以实现成固定大小,也可以是可扩展的。
    如果内存不够用,会抛出OutOfMemoryError

  2. 方法区(MethodArea):方法区是线程共享的区域(方法区是JVM启动时创建,JVM启动时只有进程,与进程绑定),被装载的class的信息存储在方法区内存中,存储了每个类的信息,如类的名称、方法信息、字段信息、静态变量、常量、类型信息以及编译器编译后的代码等。当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件内容并把它传输到虚拟机中。
    方法区虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做Non-Heap(非 堆),目的是与Java堆区分开来。
    如果内存不够用,会抛出OutOfMemoryError。

  3. 程序计数器(The pc Register)
    程序计数器记录了当前指令执行的地址,程序计数器是线程私有,每个线程都会创建程序计数器,当一个方法为native时(调到c++了),程序计数器的值为undefined,
    只有方法不是native时,程序计数器才会执行指令。
    程序计数器更像是一个指针,每执行一次指令,就会执行下一个指令

  4. 本地方法栈(Native Method Stacks)
    本地方法栈是线程私有的,用来执行native方法,如果java虚拟机栈调用本地方法栈,会通过动态链接的方式
    本地方法栈内存大小不够时抛出StackOverflowError或者OutOfMemoryError异常。

  5. 虚拟机栈(Java Virtual Machine Stacks)
    虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。换句话说,一个Java线程的运行状态,由一个虚拟机栈来保存,所以虚拟机栈肯定是线程私有的,独有的,随着线程的创建而创建。

3. Execution Engine(执行引擎)

执行引擎负责解释命令,提交操作系统执行。

4. Java Native Interface(本地方法接口)

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

回家放羊吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值