- 浏览: 124332 次
- 性别:
- 来自: 上海
文章分类
最新评论
源地址: http://developer.51cto.com/art/201009/227590.htm
你对JVM结构是否了解,这里和大家分享一下,首先看一下类文件格式,JVM使用一种硬件、操作系统无关的二进制格式来保存编译后的代码。
JVM结构
类文件格式
JVM使用一种硬件、操作系统无关的二进制格式来保存编译后的代码。
JVM结构之数据类型
和Java语言一样,JVM操作两种数据类型:基本类型和引用类型。
类型检验应该在编译期完成,JVM不需要负责类型检验。
JVM根据指令来分辨操作数的类型:
iadd->int
ladd->long
fadd->float
dadd->double
JVM显式的支持“对象”的概念。一个对象可以使一个动态分配的对象实例或一个数组。一个引用拥有引用类型。引用类型可以理解为指向对象或数组的指针。可以同时有多个引用指向一个对象实例或数组。对象实例和数组总是通过引用被操作,传递和测试(Testedviavaluesoftypereference)。
returnAddress类型
JVM中的returnAddress类型是jsr,ret和jsr_w指令。returnAddress类型是指向JVM操作码的指针。returnAddress类型不是简单意义上的数值,不属于任何一种基本类型。Java程序无法动态地修改returnAddress。
boolean类型
JVM只boolean类型提供有限的支持。没有单独的JVM指令单独操作boolean值,Java源代码中对boolean类型变量的操作被编译为int类型的指令。JVM不直接的支持boolean类型的数组,而是使用操作byte数组的指令来操作boolean数组。比如baload,bastore。Java编译器将Java语言的true和false映射为JVM中的int类型的1和0。
JVM结构之引用类型
引用类型包括三中:classtypes,arraytypes,interfacetypes。他们的值指向动态创建的类对象,数组或实现接口的类对象。一个引用可以是空的(null)。空引用不指向任何对象。空引用不属于任何类型,但是可以被转换成任何类型。JVMSpec不强制要求null在字节码中为某个值,如“0”。
运行时数据区域(RuntimeDataAreas)
JVM定义了一组运行时数据区域。这些区域再JVM运行程序时使用。一些区域在JVM启动的时候就被创建,在JVM关闭时销毁。还有些区域是每个线程所有的。线程启动时创建,线程结束时销毁。
JVM结构之pc寄存器
JVM支持多线程。每个线程都有自己的pc(programcounter)寄存器。任意时刻JVM线程执行某个方法的代码。如果方法不是native的,那么pc指向当前执行的JVM指令。如果是native的,那么pc必须足够大来保存returnAddress或一个当前pingai平台下的本地指针。
JVM栈
每个线程都拥有一个私有的JVMstack,这个堆栈与线程一同创建。JVM栈和C语言的栈相似。由于JVM的Frame可以放在堆上,所以JVMstack可以是不连续的。JVM实现者应该让程序员可以控制初始栈的大小,并控制栈的最大最小值。JVMstack可以动态增加。
Heap
JVM有一个堆,所有JVM中的线程共享这个堆。所有的类对象实例和数组都分配在堆上。
JVM堆在JVM启动的时候被创建。JVM提供一个垃圾收集者来管理堆。堆上的对象不需要程序员显式地销毁。堆可以是固定大小,也可以根据需要增加大小。堆可以是不连续的。
JVM结构之方法区域(MethodArea)
JVM有一个方法区域,所有JVM中的线程共享这个区域。这个区域与C语言程序中的“text”段类似。在其中保存了每个类属的数据,比如Runtimeconstantpool,field和methoddata,还有方法的字节码和构造函数,其中还包括类的“specialmethods”,还有实例和接口初始化代码。
Runtimeconstantpool
一个Runtimeconstantpool是代表了一个class文件中类或接口的常量表。其中包含若干常量,从编译期就固定的数值常量到编译期必须决定的方法和field的引用。Runtimeconstantpool类似与C语言中的符号表。
每个Runtimeconstantpool从JVM的MethodArea中分配。Runtimeconstantpool在类或接口被JVM创建的时候创建。
NativeMethodStack
JVM可以使用传统的堆栈来支持本地方法。
JVM结构之Frame
Frame用来存储数据,部分返回结果,也用于动态连接,返回方法的结果,以及分发异常
每次调用方法,JVM都会再当前线程的Stack上创建一个Frame,当方法结束是销毁这个Frame。
每个Frame都有自己的局部变量数组,自己的操作数栈(operandstack)。
局部变量数组和操作数栈的大小在编译期就决定了。局部变量和操作数有当前Frame所属的方法提供。
Frame的大小由虚拟机的实现者决定。Frame所占用的内存可以在方法调用的时分配。
每个线程运行的某个时刻只能有一个Frame是活跃的,称为“当前Frame”。这个线程称为“当前线程”。包含这个方法的类称为“当前类”。当一个方法调用了另一个方法,那么它的Frame不在活跃,被调用的方法的Frame成为“当前Frame”。注意:两个线程创建的Frame是完全独立的。
JVM结构之局部变量
每个Frame都有一个局部变量数组,数组的长度取决于方法的局部变量个数。
单个局部变量可以存储:boolean,byte,char,short,int,float,reference和returenAddress
一对局部变量可以存储:long或double
局部变量用索引值来取址。第一个局部变量的索引是0。
JVM使用局部变量来传递方法参数。对于类方法,方法参数从局部变量“0”(零)开始。
对于实例方法,局部变量“0”被用来保存当前实例的引用值(this)。方法参数从局部变量“1”开始。
JVM结构之操作数栈(stack)
每个Frame都包含一个LIFO的栈,称为OperandStack。该栈的最大深度在编译期决定,有创建Frame的方法代码决定。
JVM需要提供将局部变量或常量压入操作数栈的指令。其他指令可以操作栈上的数据,并将结果也压入栈。操作数栈也用于传递参数和接受返回值。
比如,iadd指令将两个int值加起来。这就需要被加的两个数在栈的最顶端。他们是由前面的指令压入栈的。两个数从栈中弹出。相加后的结果被压入栈。
动态连接(DynamicLinking)
每个Frame包含一个指向当前Runtimeconstantpool的引用,用来提供方法的动态链接。
方法代码是通过符号来引用变量和调用方法的。JVM动态的将符号翻译为具体的方法引用或变量的索引。
这就是Java实现晚绑定的机制。这种晚绑定使得代码变得更安全。
JVM结构之方法正常结束与异常结束
如果方法没有引起或抛出任何异常,那么方法会正常结束。需要指出的是,异常可以是由JVM直接抛出的,也可以是程序显式抛出的。
初始化方法
在JVM层次上,每个类的构造函数都有一个特殊的名字。这个名字由编译器提供。Java语言中不能直接使用这个名字。在JVM中,通过invokespecial指令来调用这个方法。
一个类或接口最多有一个类或接口初始化方法。这个方法是静态而且没有任何参数的。它有一个特殊的名字:。这个名字也有编译期提供,Java语言中不能直接用。类和接口的初始化方法有JVM隐式地调用。它们从不被某个JVM指令调用,而是作为类的初始化过程的一部分被调用。
异常
抛出异常会使当前方法异常结束。每个类的异常Handler被放在类文件的一个表中。
当异常发生的时候,JVM会从中找到合适的异常处理Handler来处理,如果当前方法没有合适的处理当前异常的Handler,则将当前方法的Frame弹出,扔掉Operandstack和局部变量。返回到当前方法的调用者中,再重复前面的过程,直到到达调用链条的顶端。如果最外层的方法也没有合适的Handler,就退出当前线程。
==================================================
http://www.open-open.com/lib/view/open1343121648865.html
java虚拟机在执行java程序的过程中会把它所管理的内存划分成很多个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。Java虚拟机规范中把java虚拟机所管理的内存划分为以下几个区域。
一、程序计数器(Program Counter Register)
程序计数器是一块较小的内存空间,它的作用是当前所执行的字节码的行号指示器。它是线程私有的,即各个线程都有独立的程序计数器。
如果线程正在 执行一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是native方法,则这个计数器是空(undefined)。
此内存区域是唯一的一个不会抛出OutOfMemoryError异常的区域。
二、java虚拟机栈(Java Virtual Machine Stacks)
我们可能经常听到说java内存分为堆内存和栈内存,其实这个说法中的栈内存是指java虚拟机栈中的局部变量表部分。
Java虚拟机栈描述的是java方法执行的内存模型:每个方法被执行时都会同时创建一个栈帧(Stack Frame),用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。Java虚拟机栈也是线程私有的,生命周期也线程相同。
局部变量表存放的类型包括以下三种:
1、 编译期可知的基本数据类型:boolean、byte、char、short、int、float、long、double共8 种类型;
2、 对象引用:即reference类型,它存放的是一个指向堆中对象起始地址的引用指针,或一个代表对象的句柄或者其他与此对象相关的位置,根据虚拟机的不同实现而不同;
3、 returnAddress类型:存放指向一条字节码指令的地址;
局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量表空间是完全确定了的,方法在运行期间不会改变局部变量表的大小。
Java虚拟机栈会抛出两种异常:
1、 OutOfMemoryError异常:如果虚拟本可以动态扩展,当扩展时无法申请到足够的内存时抛出;
2、 StackOverflowError异常:如果线程请求的栈深度大于虚拟机所允许的深度时抛出;
三、本地方法栈(Native Method Stacks)
本地方法栈与虚拟机栈的作用相似,它是为虚拟机在执行native方法时服务,而虚拟机栈是为虚拟机执行java方法服务。此内存区域也会抛出OutOfMemoryError异常和StackOverflowError异常。
四、java堆(Java Heap)
java堆是用于存放对象实例和数组。它是java虚拟机管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建,也是垃圾收集器管理的要区域,几乎所有的对象实例都在这里分配内存。
如果垃圾收集器采用的是分代收集它还,它还可以细分为新生代和老年代,再细致一点的有Enden空间、From Survivor空间、To Survivor空间等。
java堆可以处理物理上不连续的内存空间中,只要逻辑上连续即可。在实现时既可以实现丰固定大小的,也可以是可扩展的。如果是可扩展的,可以通过 -Xms和-Xmx来指定最小和最大值,如果-Xms和-Xmx的值相等,则相当于不可扩展了。如果堆中没有内存可完成实例分配,此内存区域会抛出 OutOfMemoryError异常。
五、方法区
方法区用于存放已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。它是堆的一个逻辑部分,是各个线程共享的内存区域。如果是sun 的HotSpot虚拟机,它也叫做永久代(Permanent Generation),如果方法区无法满足内存分配需求时,会抛出OutOfMemoryError异常。
方法区中的运行时常量池(RuntimeConstant Pool),用于存放编译期生成的各种字面量和符号引用,它在类加载后存放到运行时常量池中。
运行时常量池具有动态性,即常量不一定只在编译期产生,在运行期间也可能将新的常量存入池中,比如String类的intern()方法。
六、直接内存(DirectMemory)
它不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。比如在JDK1.4中新加入的NIO类,有一种基于通道与缓冲区的I/O 方式,它可以使用native函数库直接分配堆外内存,然后通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。所以直接内存不会受到java堆大小的限制,但会受到本机总内存的大小及处理器寻址空间的限制。它也会抛出OutOfMemoryError异常。
发表评论
-
(转)JDK工具(查看JVM参数、内存使用情况及分析等)
2018-12-25 15:50 345https://www.cnblogs.com/z ... -
[转]jstat查看jvm的GC情况
2018-12-25 15:38 553jstat 1. jstat -gc pid ... -
转一个 jmap 的基本使用方法
2017-04-05 11:52 535原文:http://hbluojiahui.bl ... -
(转)JVM内存堆布局图解分析
2017-04-05 11:56 403转载原文出处:http://www.codeceo.com/ ... -
(转)系统吞吐量(TPS)、用户并发量、性能测试概念和公式
2017-03-27 11:19 452PS:下面是性能测试的主要概念和计算公式,记录下: 一.系 ... -
(转)深入理解Major GC, Full GC, CMS
2016-11-02 11:27 499原文:http://blog.csdn.net/iter_ ... -
(转)OpenSSL 1.0.0生成p12、jks、crt等格式证书的命令个过程
2016-07-26 18:51 664OpenSSL 1.0.0生成p12、jks、crt等格式 ... -
(转)Java 内存区域和GC机制
2016-07-26 14:09 368录 Java垃圾回收概况 Java内存区域 Java ... -
Understanding CMS GC Logs
2016-07-26 11:06 532Understanding CMS GC Logs By ... -
(转)Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
2016-07-08 17:56 600源地址:http://blog.csdn.net/lu ... -
linux下查看最占性能的JAVA进程
2016-03-08 11:58 634记录一下自己常用的linux系统命令,方便以后查阅,发觉记忆 ... -
(转,精)Java 多线程 并发编程
2015-10-10 19:50 800源地址:http://blog.csdn.n ... -
java虚拟机内存监控工具jps,jinfo,Jstack,jstat,jmap,jhat使用
2015-09-21 13:14 1202源地址:http://my.oschina. ... -
(转)JMM模型
2014-11-11 16:53 488源地址:http://blog.csdn.net/gt ... -
(转)《深入浅出 Java Concurrency》目录
2014-11-10 15:55 402原文地址:http://www.blogjava.net/x ... -
(转)TCP/IP、Http、Socket的区别
2014-08-21 10:32 813源地址: http://jingyan.baidu.com/ ... -
(转)Swift里的CAP理论和NWR策略应用
2014-08-12 17:25 612源地址:http://blog.sina.com.cn/s/ ... -
(转)Java多线程编程的常见陷阱
2014-06-25 13:14 498源地址:http://developer.51cto.com ... -
(转)Java 正确的做字符串编码转换
2014-03-11 21:52 657原文:http://hi.baidu.com/sodarf ... -
深入理解java内存模型系列文章
2013-12-30 10:57 438深入理解java内存模型系列文章 源地址: htt ...
相关推荐
JVM演讲PPT分享 本次分享的核心内容围绕Java虚拟机(JVM)及其在运行Java程序...通过以上内容的深入学习,可以对JVM有一个全面的认识,理解它在Java生态系统中的核心地位,以及如何通过学习JVM来提升Java程序的性能。
通过以上分析,我们对JVM中的类加载子系统有了较为全面的认识。类加载子系统不仅是JVM的核心组成部分之一,也是理解Java程序运行机制的关键。掌握类加载的过程和机制对于提升Java开发者的技能具有重要意义。在未来的...
1. **JVM结构**:JVM由类加载器、运行时数据区、执行引擎、本地方法接口和本地库组成。理解这些组成部分的功能对于理解JVM如何工作至关重要。 2. **类加载机制**:包括加载、验证、准备、解析和初始化五个阶段,...
《深入了解JVM(Inside Java Virture ...《Inside Java Virtual Machine》一书深入剖析了JVM的各个方面,结合博文学习,你将能够对JVM有更全面、深入的认识,从而更好地驾驭Java编程,提升软件开发的效率和质量。
描述:“主要深入讲解jvm知识,对jvm有一个更全面的理解” 标签:“jvm” 核心知识点解析: 一、Java虚拟机(JVM)概念 Java虚拟机是一个抽象的计算机模型,由软件在实际计算机上模拟实现。它具有自己的硬件架构...
本书《深入理解Java虚拟机:JVM高级特性与最佳实践》将带领读者深入到JVM的内部世界,全面地理解其各个组成部分的工作机制。全书分为五个部分,每个部分都深入浅出地介绍了JVM的不同方面。 在第一部分中,作者回顾...
通过对编程语言、程序设计、编程范式、Java运行机制和开发环境的介绍,使读者对Java编程有了全面的认识。通过实际编写和运行Java程序,读者可以加深对Java程序设计的理解,为进一步学习和应用Java语言打下坚实的基础...
- **库文件**:Java提供了一个全面的类库,覆盖了从基本数据结构到高级功能的所有方面。 - **类与结构体和联合体**:Java使用类来表示数据结构和行为,而非C/C++中的结构体和联合体。 **1.2.5 Java在应用领域的优势...
Java编程语言是世界上最流行的编程语言之一,尤其在...通过系统学习,初学者可以逐步建立起对Java编程的全面认识,为后续的进阶学习打下坚实基础。在实践中不断练习和巩固这些知识点,你将成为一名熟练的Java程序员。
根据提供的文档信息,我们可以归纳出以下关键知识点: ...通过以上知识点的学习,初学者能够对Java的基础结构、平台无关性以及基本数据类型有较为全面的认识。这对于进一步深入学习Java编程语言是非常重要的。
总的来说,Java类加载原理是Java程序员进阶的必修课,它涉及到了JVM的内部运作机制,深入理解可以帮助我们更好地优化程序性能,解决一些棘手的问题,同时也能让我们对Java平台有更全面的认识。通过阅读相关文章和...
《Core Java终结版》是针对Java初学者的一份详尽且深入的学习材料,由何兆睿编撰,旨在为读者提供全面的Java基础知识和技术要点。本文将基于此书的目录和部分章节内容,提炼出一系列重要的Java知识点,帮助读者更好...
- **集合框架概述**:认识Java集合框架的组成(List、Set、Map等),了解它们之间的关系及应用场景。 - **List与Set的区别**:理解List与Set的具体差异(有序性、重复性等),并能根据实际需求选择合适的集合类型。 ...
《编译原理》是计算机科学领域的一门核心课程,它主要研究如何将高级程序设计语言转换为机器可执行的指令。...同时,编译原理也是计算机科学理论基础的重要组成部分,有助于培养对计算机系统的全面认识。
- 对JVM内存结构、对象内存布局、类加载器、字节码技术和JVM参数调优的了解,以及对各种垃圾收集器原理的掌握,如Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1、ZGC等,这都是性能调优的...
通过这些内容的学习,学员们能够对整个程序的生命周期有更全面的认识,从而更有效地进行程序设计和优化。 综上所述,《程序设计语言与编译》这门课程,不仅能够帮助初学者打下坚实的编程基础,而且能够帮助有经验的...
总而言之,“Java入门精典源代码”是一个宝贵的资源,通过阅读和实践其中的代码,你可以逐步建立起对Java编程的全面认识,为后续的进阶学习打下坚实的基础。无论你是打算从事Web开发、移动应用开发还是大数据处理,...
### Java基础教程知识点详解 #### 一、Java的历史与背景 **1.1 Java的起源** Java语言最初来源于Sun ...通过以上内容的学习,初学者可以对Java语言有一个较为全面的认识,为进一步深入学习Java打下坚实的基础。
Tomcat 8是Java Web应用程序开发的重要组成部分,它提供了轻量级、高效且稳定的运行环境。这本书详细介绍了Tomcat 8的安装、配置、管理和优化,以及与之相关的各种技术。 首先,本书会讲解Tomcat 8的基础知识,包括...
Java是一种广泛使用的面向对象的编程...总之,“java入门ppt”是初学者理想的起点,通过系统的讲解和实例,能够帮助新手逐步建立起对Java编程的全面认识。同时,学习者应配合实际编程练习,不断巩固和提升自己的技能。