【JVM学习系列】 JVM内部架构

来源:互联网 发布:python config 编辑:程序博客网 时间:2024/06/14 19:00

我们都知道字节码是由JRE解析执行的,但是可能并未了解JRE本身其实是对JVM的一种实现,JVM定义了如何去分析字节码、如何去解析字节码的意义以及如何去执行解析后的字节码.作为Java开发人员,如果我们对JVM的体系结构有一定程度的深入了解,将会有益于我们写出更加高效的Java应用.

本文先对JVM的架构进行了大致的了解,在后续的章节中会对其中的每个部分进行深入的探讨.

下面是JVM体系的概念图:

jvm内部架构

为了方便解释和理解,我们暂且将整个JVM体系结构粗略地划分为三个部分构成:

  • Class Loader SubSystem(类加载子系统)
  • Runtime Data Areas(运行时数据域)
  • Execution Engine(执行引擎)

下面对整个图中的组成部分进行简单的介绍.

1. Class Loader SubSystem

我们编写Java程序编译后是class文件,JVM就是解析执行这些编译后的class文件,因此JVM第一步工作就是加载class文件到JVM环境中.

在上图中我们看到Class Loader SubSystem模块中可以进一步细分为多个小阶段:

  1. Loading: 这个阶段就是读取class文件;
  2. Linking: 在loading阶段完成读取class文件后,我们得验证class文件本身的有效性,这个阶段会对class文件进行解析;
  3. Initialization: 在前两个阶段工作的基础上,初始化加载的Class中的静态执行代码;

2. Runtime Data Areas

这个部分主要是对JVM运行时,内部存储空间的分配布局进行介绍.

从图中我们可以大致了解这个部分主要由5个部分组成:

  • Method区域

    这个部分是Class级别数据存放的地方,包括静态变量. 每个JVM运行实例中只会存在一个Method区域,它是共享的资源

  • Heap区域

    这个部分是所有对象和数组保存的地方,Heap区域Method区域一样,也是一个JVM实例中只有一个,多个线程共享这块heap区域,因此这块存储区域的数据是线程不安全的,需要借助某种机制来控制线程间的访问.

  • Stack区域

    对于每个线程,JVM对会分别为其创建其专属的Stack区域,每次方法调用的时候,都会创建一个调用栈放到Stack区域,Stack区域是线程安全的.

  • PC寄存器

    每个线程都拥有独自的PC寄存器,该寄存器用来指示当前线程所执行指令的地址,概念和我们平常系统里面的PC寄存器保持一致.

  • Native Method Stacks(本地方法调用栈)

    这个区域也是每个线程有独立的区域,目的是用来保存native方法的信息.

3. Execution Engine

这部分是字节码真正被解析执行的地方,执行引擎读取字节码然后逐个的去执行.

首先,字节码由Interpreter(解析器)去解析,解析器解析字节码速度比较的快但是执行比较忙,这基本是解释性语言的通病.

为了解决解释执行的执行速度慢的缺点,JVM引入JIT编译器(Just-in-time),这个编译器将频繁执行的字节码直接编译成本地代码,这样下次执行同样代码的时候就不要再解析执行了,这样速度就得到了很大的提升.

Garbage Collector(垃圾回收器): 想必这部分大家也经常在Java语言特性中了解,Java并不需要像C语言那样,自己释放使用的内存(例如: free的调用),而是通过垃圾回收机制来实现,有效避免内存泄漏问题的发生.

Java Native Interface(JNI): 这是Java程序与本地库通信约定的接口,用于Java程序调用本地系统的服务.

Native Method Libraries:这个是执行引擎执行过程需要的本地库,这些库提供Java程序运行过程中需要的系统服务,例如:读取文件,这些最终都会调用本地系统的服务,这些服务通过这些库封装,然后JVM通过JNI接口实现调用.

参考:

  1. http://www.javainterviewpoint.com/java-virtual-machine-architecture-in-java/
1 0
原创粉丝点击