引用
http://thw.iteye.com/blog/953869
1 JVM 简介
JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后会写个复杂点class ,然后再找一些开源框架,比如Spring ,Hibernate 等等,再然后就开发企业级的应用,比如网站、企业内部应用、实时交易系统等等,直到某一天突然发现做的系统咋就这么慢呢,而且时不时还来个内存溢出什么的,今天是交易系统报了StackOverflowError ,明天是网站系统报了个OutOfMemoryError ,这种错误又很难重现,只有分析Javacore 和dump 文件,运气好点还能分析出个结果,运行遭的点,就直接去庙里烧香吧!每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了。我想Java 做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢?—— JVM 。
JVM 全称是Java Virtual Machine ,Java 虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare 不一样,那个虚拟的东西你是可以看到的,这个JVM 你是看不到的,它存在内存中。我们知道计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,那这个JVM 也是有这成套的元素,运算器是当然是交给硬件CPU 还处理了,只是为了适应“一次编译,随处运行”的情况,需要做一个翻译动作,于是就用了JVM 自己的命令集,这与汇编的命令集有点类似,每一种汇编命令集针对一个系列的CPU ,比如8086 系列的汇编也是可以用在8088 上的,但是就不能跑在8051 上,而JVM 的命令集则是可以到处运行的,因为JVM 做了翻译,根据不同的CPU ,翻译成不同的机器语言。
JVM 中我们最需要深入理解的就是它的存储部分,存储?硬盘?NO ,NO , JVM 是一个内存中的虚拟机,那它的存储就是内存了,我们写的所有类、常量、变量、方法都在内存中,这决定着我们程序运行的是否健壮、是否高效,接下来的部分就是重点介绍之。
2 JVM 的组成部分
我们先把JVM 这个虚拟机画出来,如下图所示:
从这个图中可以看到,JVM 是运行在操作系统之上的,它与硬件没有直接的交互。我们再来看下JVM 有哪些组成部分,如下图所示:
该图参考了网上广为流传的JVM 构成图,大家看这个图,整个JVM 分为四部分:
q Class Loader 类加载器
类加载器的作用是加载类文件到内存,比如编写一个HelloWord.java 程序,然后通过javac 编译成class 文件,那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任,那不可能随便建立一个.class 文件就能被加载的,Class Loader 加载的class 文件是有格式要求,在《JVM Specification 》中式这样定义Class 文件的结构:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
需要详细了解的话,可以仔细阅读《JVM Specification 》的第四章“The class File Format ”,这里不再详细说明。
友情提示:Class Loader 只管加载,只要符合文件结构就加载,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。
q Execution Engine 执行引擎
执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。
q Native Interface 本地接口
本地接口的作用是融合不同的编程语言为Java 所用,它的初衷是融合C/C++ 程序,Java 诞生的时候是C/C++ 横行的时候,要想立足,必须有一个聪明的、睿智的调用C/C++ 程序,于是就在内存中专门开辟了一块区域处理标记为native 的代码,它的具体做法是Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies 。目前该方法使用的是越来越少了,除非是与硬件有关的应用,比如通过Java 程序驱动打印机,或者Java 系统管理生产设备,在企业级应用中已经比较少见,因为现在的异构领域间的通信很发达,比如可以使用Socket 通信,也可以使用Web Service 等等,不多做介绍。
q Runtime data area 运行数据区
运行数据区是整个JVM 的重点。我们所有写的程序都被加载到这里,之后才开始运行,Java 生态系统如此的繁荣,得益于该区域的优良自治,下一章节详细介绍之。
整个JVM 框架由加载器加载文件,然后执行器在内存中处理数据,需要与异构系统交互是可以通过本地接口进行,瞧,一个完整的系统诞生了!
2 JVM 的内存管理
所有的数据和程序都是在运行数据区存放,它包括以下几部分:
q Stack 栈
栈也叫栈内存,是Java 程序的运行区,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就Over 。问题出来了:栈中存的是那些数据呢?又什么是格式呢?
栈中的数据都是以栈帧( Stack Frame )的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法 (Method) 和运行期数据的数据集,当一个方法 A 被调用时就产生了一个栈帧 F1 ,并被压入到栈中, A 方法又调用了 B 方法,于是产生栈帧 F2 也被压入栈,执行完毕后,先弹出 F2 栈帧,再弹出 F1 栈帧,遵循“先进后出”原则。
那栈帧中到底存在着什么数据呢?栈帧中主要保存3 类数据:本地变量(Local Variables ),包括输入参数和输出参数以及方法内的变量;栈操作(Operand Stack ),记录出栈、入栈的操作;栈帧数据(Frame Data ),包括类文件、方法等等。光说比较枯燥,我们画个图来理解一下Java 栈,如下图所示:
图示在一个栈中有两个栈帧,栈帧2 是最先被调用的方法,先入栈,然后方法2 又调用了方法1 ,栈帧1 处于栈顶的位置,栈帧2 处于栈底,执行完毕后,依次弹出栈帧1 和栈帧2 ,线程结束,栈释放。
q Heap 堆内存
一个JVM 实例只存在一个堆类存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,以方便执行器执行,堆内存分为三部分:
Permanent Space 永久存储区
永久存储区是一个常驻内存区域,用于存放JDK 自身所携带的Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM 才会释放此区域所占用的内存。
Young Generation Space 新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space )和幸存者区(Survivor pace ),所有的类都是在伊甸区被new 出来的。幸存区有两个: 0 区(Survivor 0 space )和1 区(Survivor 1 space )。当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存0 区。若幸存0 区也满了,再对该区进行垃圾回收,然后移动到1 区。那如果1 区也满了呢?再移动到养老区。
Tenure generation space 养老区
养老区用于保存从新生区筛选出来的JAVA 对象,一般池对象都在这个区域活跃。 三个区的示意图如下:
q Method Area 方法区
方法区是被所有线程共享,该区域保存所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
q PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码,由执行引擎读取下一条指令。
q Native Method Stack 本地方法栈
分享到:
相关推荐
JVM组成及工作原理 JVM(Java Virtual Machine)是一种基于栈的虚拟机,它是Java程序的运行环境。JVM主要由两个子系统和两个组件组成。两个子系统分别是Classloader子系统和Executionengine子系统;两个组件分别是...
JVM的内容分享,包含JVM的优化目标、优化原则、JVM组成、内存区域划分、垃圾回收算法、垃圾回收器、FullGC触发时机、对象布局、元空间存储、GC调优
了解JVM的组成及其工作原理对于提升Java应用程序的性能至关重要,它可以帮助开发者更好地诊断和解决内存泄漏、性能瓶颈等问题。通过对JVM底层工作原理的深入理解,开发者能够对Java程序的运行进行更精细的调优,比如...
### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心在于源文件的编译与执行。不同于 C/C++ 这类需要针对不同平台进行编译的语言,Java 采用了一种更为灵活的...
详解JVM组成,GC,内存区域,以及一些GC机制和算法,一些简单的调优
JVM组成 GC回收算法 Java引用,GC垃圾收集器,OOM 类加载,类加载器 对象初始化 编译 JiT:即时编译 两大无关性 平台无关性: 每一台平台解释器不同,但是虚拟机相同,跨平台的原因。 一个程序对应一个虚拟机,多个...
一、JVM组成部分 1. 程序计数器(PC Register):它是线程私有的,用于记住下一条JVM指令的执行地址。由于线程是相互独立的,所以计数器是每个线程独有的,不会存在内存溢出的问题。 2. Java虚拟机栈(JVM Stacks...
Java虚拟机(JVM)是Java程序的运行环境,它的主要组成部分包括ClassLoader、Runtime Data Area、Execution Engine和Native Method Library。JVM的运行流程是:ClassLoader将Java代码转换为字节码,Runtime Data ...
#### 一、JVM组成与特性 JVM(Java Virtual Machine)即Java虚拟机,它是运行Java程序的核心组件之一。通过理解JVM的组成部分,可以帮助开发者更好地进行程序开发与优化。 ##### 1. 组成部分 - **寄存器**:用于...
2. **JVM组成部分** - **类加载子系统**:负责加载、验证和初始化类。 - **运行时数据区**:包括堆、栈、方法区等,存储类信息、对象信息和执行逻辑。 - **执行引擎**:解释执行字节码和进行垃圾收集(GC)。 - ...
总结来说,JVM是Java编程的重要组成部分,它的启动过程涉及到类加载、验证、准备、解析和初始化等多个阶段。理解这些原理有助于我们更好地编写和调试Java代码,提升程序性能。通过深入研究JVM,开发者可以更好地解决...
jvm内存模型组成部分
1、jvm组成以工作流程 jvm组成 类装载器、运行时数据区(内存模型)、字节码执行引擎 工作大致流程 首先我们的java类编译成class类文件,当我们的class文件开始执行,我们的虚拟机便开始工作。 类加载器将class加载...
类加载器子系统是 JVM 的一个重要组成部分,它负责加载 Java 类文件,并将其转换为 JVM 可以识别的字节码。类加载器子系统包括启动类加载器、扩展类加载器、系统类加载器和用户自定义加载器四个部分。它们分别负责...
1. **JVM架构**:JVM主要由类装载器、运行时数据区、执行引擎、本地方法接口和本地库组成。了解每个部分的功能对于优化程序性能至关重要。 2. **类装载机制**:包括加载、验证、准备、解析和初始化五个阶段,确保类...
#### JVM的组成结构 JVM由多个关键组件构成,包括类加载器(ClassLoader)、执行引擎(ExecutionEngine)和本地接口(NativeInterface): 1. **类加载器**:负责将类文件加载到内存中。它遵循严格的格式规范,...
- JVM是Java平台的核心组成部分,它是一个运行Java字节码的虚拟机,负责执行Java程序。 - JVM实现了Java的跨平台特性,即“一次编写,到处运行”。 2. **类加载机制**: - 类的生命周期包括加载、验证、准备、...
JVM的内存模型由运行时数据区和本地接口组成: - **运行时数据区**:是JVM在运行期间,用于存储数据的内存区域,包括方法区、堆、虚拟机栈、本地方法栈和程序计数器。 #### 6. 内存模型中的重要概念 - **方法区**:...
Java虚拟机(JVM)是Java编程语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能够在不同的操作系统上“一次编写,到处运行”。JVM是Java平台的一部分,负责执行字节码,管理内存,垃圾收集,以及提供...
JVM主要由类加载子系统、运行时数据区、执行引擎、本地方法接口和本地方法库五个部分组成。其中,类加载子系统负责加载、验证、准备和初始化类文件;运行时数据区包括堆、栈、方法区、程序计数器和本地方法栈,它们...