简单介绍JVM各组成部分
图1 JVM组成部分
JVM包含两个子系统和两个组件
两个子系统:类加载子系统(Class loader)和执行引擎(Execution engine)
两个组件:运行时数据区(Runtime data area)、本地接口(Native Interface)。
类加载子系统(Class loader)
根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area。
注: Class Loader 只管加载符合文件结构的class文件,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。
执行引擎(Execution engine)
执行引擎也叫作解析器(Interpreter),负责解析命令,提交操作系统执行。执行classes中的指令。
运行时数据区(Runtime data area)
运行数据区是整个JVM的重点,java虚拟机在执行java程序的过程中会把他所管理的内存划分为若干个不同的数据区域:Method Area(方法区)、VM stack(虚拟机栈)、Native Method Stack(本地方法栈)、Heap(堆)、Program Counter Register(程序计数器)。
方法区(Method Area)
图2
主要存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(比如spring 使用IOC或者AOP创建bean时,或者使用cglib,反射的形式动态生成class信息等)。
注: JDK 6 时,String等字符串常量的信息是置于方法区中的,但是到了JDK 7 时,已经移动到了Java堆。所以,方法区也好,Java堆也罢,到底详细的保存了什么,其实没有具体定论,要结合不同的JVM版本来分析。
异常:
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError。
运行时常量池溢出:比如一直往常量池加入数据,就会引起OutOfMemoryError异常。
虚拟机栈(VM stack)
本地方法栈(Native Method Stack)
堆(Heap)
程序计数器(Program Counter Register)
本地接口(Native Interface)
本地接口的作用是融合不同的编程语言为Java 所用,初衷是融合C/C++ 程序。Java 诞生的时候是C/C++ 横行的时候,要想立足,必须有一个聪明的、睿智的调用C/C++ 程序,于是就在内存中专门开辟了一块区域处理标记为native 的代码。具体做法是Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies(本地方法库) 。
目前该方法使用的是越来越少了,除非是与硬件有关的应用,比如通过Java 程序驱动打印机,或者Java 系统管理生产设备,在企业级应用中已经比较少见,因为现在的异构领域间的通信很发达,比如可以使用Socket 通信,也可以使用Web Service 等等。