深入理解Java虚拟机学习笔记综述.docx

  1. 1、本文档共17页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
JVM的自动内存管理机制一如何划分JVM内存JVM所管理的内存在运行时会被分为这样几个数据区:虚拟机栈区,堆区,方法区,本地方法栈,程序计数器。程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,每条线程都需要有一个独立的程序计数器,各条线程之间程序计数器互不影响,独立存储,是线程隔离的。程序计数器所在的内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。虚拟机栈,线程私有,它的生命周期与线程相同。虚拟机栈区描述的是Java方法执行内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。局部变量表存放了8种基本数据类型、对象的引用和returnAddress。局部变量表所需的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小。本地方法栈,作用与虚拟机栈区是相似的,他们之间的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。堆,Java堆,也称GC堆,是最大的一块,是被线程共享的区域,在虚拟机启动时创建。所有类的实例(对象)和数组都是在堆上分配内存的,堆内存由存活和死亡的对象,空闲碎片区组成,对象所占的堆内存是由自动内存管理系统回收。(数组是一种对象)从内存回收角度来看,Java堆还可以细分为新生代和老年代;甚至还可以分为Eden空间、 From Survivor空间、To Survivor空间等。从内存分配角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(TLAB)。Java堆可以处于物理上不连续的内存中,只要逻辑上连续即可。方法区在JVM中也是一个非常重要的区域,在HotSpot虚拟机上,方法区被称为“永久代”。虽然Java虚拟机规范把方法区描述为堆区的一个逻辑部分,但还是要区分来对待。方法区用于存储已被JVM加载的类信息(包括类的名称、方法信息、字段信息)、类变量(静态变量)、常量、即时编译器编译后的代码等数据。虽然方法区中有些数据是线程隔离的,但是编译器编译后的代码等数据,是线程共享的。除了和Java堆一样不需要连续的内存和可以固定大小或者可扩展外,还可以选择不实现垃圾收集。但不并非方法区就不要内存回收了,方法区的内存回收只要针对常量池的回收和对类型的卸载。运行时常量池,是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用。二对象的创建在语言层面上,创建对象通常仅仅是一个new关键字而已。但在虚拟机中,对象的创建过程大致分为以下四步:第一步,检查类加载。虚拟机遇到一条new指令时,首先需要去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。第二步,分配内存。在类加载检查通过后,接下来虚拟机将为新生对象分配内存。对象所需的内存大小在类加载完成后便可完全确定。分配方式大致有两种:指针碰撞和空闲列表。除了考虑如何划分可用空间之外,还需要考虑在并发的情况下的线程安全。解决方案有两种:一种是对分配空间的动作进行同步处理;另外一种本地线程分配缓冲(TLAB)。第三步,内存空间初始化。如果使用TLAB,这一过程可以提前至TLAB分配时进行。第四步,必要的设置。初始化后,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头中。上面的工作完成后,从虚拟机角度来看,一个新的对象已经产生了,但在程序员的角度来看,对象的创建才刚刚开始,init方法还没有执行,所有字段都还为零。所以,一般来说,执行new指令后会接着执行init方法,把对象按照程序员的意愿进行初始化,这样一个可用的对象才算完全产生出来。三对象的内存布局在HotSpot虚拟机中,对象在内存中存储的布局分为3块:对象头、实例数据和对齐填充。对象头包括两部分信息,一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁等;另一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型字段内容。无论是从父类继承下来,还是在子类中定义的,都需要记录。这部分的存储顺序会受到虚拟机分配策略参数和字段在Java源码中的顺序的影响。对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。

您可能关注的文档

文档评论(0)

希望之星 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档