热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java虚拟机_JVM内存结构《深入理解Java虚拟机》学习总结

篇首语:本文由编程笔记#小编为大家整理,主要介绍了JVM内存结构---《深入理解Java虚拟机》学习总结相关的知识,希望对你有一定的参考价值。本文转自:http://ww

篇首语:本文由编程笔记#小编为大家整理,主要介绍了JVM内存结构---《深入理解Java虚拟机》学习总结相关的知识,希望对你有一定的参考价值。


本文转自:http://www.cnblogs.com/jilodream/,作者:王若伊_恩赐解脱

 

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域的用途各不相同,同时也依据着各自的执行规则,独立的创建和销毁数据。

虚拟机内存的划分,如图所示:

技术分享

线程之间互相独立的区域有:

虚拟机栈 、本地方法栈、程序计数器

线程可以共享数据的区域:

方法区 、堆

每个区域的作用分别如下:

程序计数器 Program Counter Register:

众所周知,虚拟机处理多线程时,是通过轮流的切换线程,来获取cpu的执行机会的。在虚拟机执行程序的过程中,当线程执行到某一位置时,虚拟机将cpu的执行机会出让给了其他线程,此时原有线程的执行位置需要被记录下来,而新得到执行机会的线程,又需要提供上次执行的位置,以此来保证程序中的多个线程可以持续的并行的执行下去。

程序计数器的作用就是将各个线程下次所执行的(字节码)行号(准确来说是指令的地址)记录下来,以保证其下次执行时可以正确的执行。

根据程序计数器的作用,我们可以知道:

1、每个线程都在这个区域中都应该拥有一个只为自己提供服务的程序计数器,它们之间是独立存储,互不影响的存在。

2、我们还可以知道,程序计数器只记录字节码的行号,因此当线程执行本地方法(Native method)时,计数器的值是空。

3、程序计数器所耗费的内存空间非常小,因此这个区域是不会抛出OutOfMemoryError错误的。

虚拟机栈 VM Stack:

线程想要正常的运行下去,单靠程序计数器来记录行号是远远不止的。线程还需要拥有自己的运行空间,在这个空间中,虚拟机可以保存方法的执行顺序、方法的内部局部变量,方法在运算时,所需要的内存空间等。

在数据结构中,栈的特性最满足方法的进入返回的结构的。而这块区域的主要作用就是线程在执行java方法时所需要记录的数据。因此我们将这块区域称之为虚拟机栈。但是要记住这里与我们在工作中通常指的栈并不等同,这个我会在后边介绍。

虚拟机栈的结构如下:

技术分享

而对于每一个栈帧内部的划分又是这样的:

技术分享

每一部分的作用如下:

局部变量表:每一个方法都可以定义一个只属于自己的局部变量,当这个方法运行结束后,这个局部变量的生命周期也就宣告结束。所以每一个方法都应该拥有一个块属于自己的内存区域用来保存方法内部定义的局部变量。这块区域就是局部变量表,我们平常工作中所指的栈,实际上指的是虚拟机栈中的栈帧中的局部变量表。

操作数栈:每个方法的内部都可以计算数据,而计算数据势必需要拥有一块内存区域,为虚拟机用来进行数值计算。因此在栈帧中,就需要有一块区域专门为当前方法计算数据使用,它就是操作数栈。

在每进行一次完整的计算之后,栈中的数据都已经出栈,所以操作数栈的空间在一个方法内部是可以反复使用的。所以虚拟机在分配内存大小时,只分配当前方法,单次完整计算所需要的最大内存空间给当前栈帧,以减少内存的消耗。

同时为了增加运行效率,减少数据的不断复制,在大部分虚拟机的实现中,将当前方法的局部变量表和上层方法的操作数栈的内存形成部分重叠,从而减少参数的不断复制而引起的性能消费。

动态连接:

虚拟机在执行方法时有两种形式被用来确定执行指令所对应的方法,

第一种是类加载时,可以直接确定要执行的方法,譬如静态方法,私有方法,final方法等。这种形式叫做静态解析。

第二种是在真正运行时,根据对象的真实引用来判断当前真正要执行的方法。这种形式称之为动态连接。

在字节码文件中,都存在一个常量池,在这个常量池中保存有大量的符号引用,这个符号引用是每一个方法的间接引用。在字节码指令的中,使用的是这个符号引用。但是在运行时阶段,肯定需要调用到要执行方法在内存中真实的地址。这就需要将间接引用转化成直接引用。而这里的“动态连接”就是为了保证在运行时阶段,方法可以正确的找到要调用的方法,每个栈帧将自己在运行时常量池中所对应的真实地址记录的位置。

这里需要注意的是,在栈帧中的动态连接和查找符号引用为真实引用中的动态连接,是两个概念。前者表示的是一个区域,后者表示的是一种查找方式。

返回地址:

退出当前方法的方式有两种,第一种是遇到返回指令时,正常的退出当前方法。另一种形式是遇到没有捕获而被抛出的异常。无论何种返回形式,在方法退出后,栈帧的顶端都应是当前退出方法的上层方法。同时上层方法的执行状态也需要根据当前的返回结果重新调整。所以每个栈帧可以利用“返回地址”这块区域帮助上层方法恢复状态。

附加信息:对于虚拟机规范中没有申明的,拥有指定存放位置的信息可以由各个虚拟机自己决定,放置到这个区域中。

本地方法栈 Native Stack

在虚拟机中,不但运行java方法,还会运行本地方法,也就是常见的Native 关键字修饰的方法。在虚拟机栈中,会为每个线程独立的开辟一个专门运行java语言(更准确的说应该是字节码)的方法栈,但是对于本地方法,则是使用另外的一块内存区域来保存线程的调用状态,这块区域就是本地方法栈。他的作用跟虚拟机栈基本相似,其区别就是一个为java方法服务,一个为Native发光法服务。在虚拟机规范中,对于本地方法栈中的结构、方法的语言、方式,都没有强制规定,各个虚拟机可以自由的实现它。

Java堆 Java Heap

我们平常所说的,在堆中创建一个实例,指的就是这个堆。这是虚拟机所管理的内存中最大的一块。在虚拟机中,几乎所有的实例以及数组所分配的内存空间都会被放置在这个堆中。

由于java堆是对象实例的的主要存放位置,因此虚拟机的垃圾回收机制的主要工作区域。

根据Java的内存回收机制,我们可以将堆的大小和内容划分成如下的形式:

技术分享

根据java堆的特性,我们也可以知道,这块区域是一块线程共享的区域。同时我们也可以看出来,这块区域,所可以使用在物理上非连续的内存,只要在逻辑上保持连续即可。

方法区 Method Area

方法区的主要作用是保存类信息、常量、静态变量以及即时编译后的代码等数据。这个区域中的数据仍然会被GC的代回收所涉及到。我们平常所说的永久代,指的就是这个区域。

尽管这个区域也被称之为永久代,但是当数据进入这个区域中,仍然可能会被回收。这个区域的回收目标主要是常量池的回收,以及类型的卸载。

运行时常量池 Runtime Constant Pool

这块区域属于方法区的中的一块子区域。

在Class文件中,除了有类版本、字段、方法、接口等,还有一个信息区域是常量池。常量池中的数据将会在类被加载后,存在到运行时常量池中。

而类文件中的常量池主要包括各种字面量和符号引用。符号引用在讲解栈帧时,有所涉及。

字面量可以理解为java语言中的常量,如字符串、final修饰的变量等。

符号引用则是指以下三种固定信息:

类和接口的全限定名称

字段的名称和描述符

方法的名称和描述符

java语言在编译成Class文件后,并没有关于方法和字段在内存中最终布局的信息。所以当虚拟机使用这些变量或方法时,需要先从常量池中,找到这些数据对应的符号引用,然后在方法的栈帧中的动态连接区域中找到其对应的内存真实位置。

在日常工作中,我们经常会遇到两种内存溢出的错误:

1、OutOfMemoryError

2、StackOverflowError

OutOfMemoryError指的是一个区域中,由于数据的不断增加,导致区域无法再从物理内存总申请到更大的空间,或者是区域所申请的空间已经到达虚拟机运行参数所给该区域设定的最大值,那么就会抛出这个错误。

StackOverflowError则指的是内存中的栈结构在不断的入栈,最终导致栈的深度超过了虚拟机所允许的栈深度时,所抛出的错误。


推荐阅读
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 生产环境下JVM调优参数的设置实例
     正文前先来一波福利推荐: 福利一:百万年薪架构师视频,该视频可以学到很多东西,是本人花钱买的VIP课程,学习消化了一年,为了支持一下女朋友公众号也方便大家学习,共享给大家。福利二 ... [详细]
author-avatar
靜trevis_263
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有