首先我想从宏观上介绍一下Java虚拟机的工作原理。从最初的我们编写的Java源文件(.java文件)是如何一步步执行的,如下图所示,首先Java源文件经过前端编译器(javac或ECJ)将.java文件编译为Java字节码文件,然后JRE加载Java字节码文件,载入系统分配给JVM的内存区,然后执行引擎解释或编译类文件,再由即时编译器将字节码转化为机器码。主要介绍下图中的类加载器和运行时数据区两个部分。
JVM的整体架构
类加载子系统:
---负责从文件系统或者网络中加载class信息,存入方法区中。Java类的加载、连接和初始化都是在程序运行时完成的,只有在类被需要的时候才进行动态加载,更多的内容可以看类加载子系统的解析过程。Java的详解:JVM的类加载子系统的解析过程 – Break易站
方法区(Method Area):
存放加载后的class信息,包括静态方法,jdk1.6以前包含了常量池。更多的方法区在类加载的时候,究竟存储了什么呢?可以移步:Java虚拟机(JVM)的方法区(Method Area)存储了什么内容? – Break易站
参数:-XX:PermSize初始值 -XX:MaxPermSize最大值
Java堆(Heap):
Java工程的主要内存工作区域,所有线程共享,jdk1.7以后包含了常量池。参数: -Xms初始值 -Xmx最大值
直接内存:java堆外,直接向系统申请的内存区间,允许NIO库使用。申请空间慢,读写快。默认下最大可用空间等于堆的最大可用空间。在server模式下,读写速度是堆的10倍。
参数:-XX:MaxDirectMemorySize 最大值
垃圾回收器:
Java栈:线程私有,用于存放局部变量,方法参数,同时和java方法的调用返回密切相关。
参数:-Xss最大值
本地方法栈:和java栈类似,主要用于本地方法调用。
PC寄存器:线程私有
执行引擎:
Java [-options] class [args...]
其中-options是java虚拟机的启动参数,args是传递给main方法的参数、
从Java平台的逻辑结构上来看,我们可以从下图来了解JVM:
从上图能清晰看到Java平台包含的各个逻辑模块,也能了解到JDK与JRE的区别,对于JVM自身的物理结构,我们可以从下图鸟瞰一下:
JVM的运行如下图:
从图中,可知内存分为线程私有和共享两大类:
(1)线程私有区,包含以下3类:
程序计数器,记录正在执行的虚拟机字节码的地址;
虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
本地方法栈:虚拟机的Native方法执行的内存区;
(2)线程共享区,包含以下2类
Java堆:对象分配内存的区域;
方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据;
常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。