之前由于考研,对于虚拟机的认识疏忽了太多,现在重新整理回顾一下。

如上图所示,jvm的内存区域(运行时数据区)共分为5处:方法区(Method Area)、虚拟机栈(vm Stack)、本地方法栈(Native Method Stack)、堆(Heap)和程序计数器(Program Counter Register)

程序计数器:它是一块内存较小的区域,可以看成是线程所执行的字节码的行号指示器,字节码解释器运行时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。在java虚拟机中,多线程的运行采用的的是线程轮流切换机制,所以每条线程都需要建立一个独立的程序计数器,它是线程私有的。

虚拟机栈:它和程序计数器一样,也是线程私有的,它的作用是当java线程运行时,java方法在执行的同时会建立一个栈帧,用来存储局部变量表、操作数栈、动态链接,方法出口等信息。每个java方法从调用到执行完成的过程,就对应着一个栈帧从入栈到出栈的过程。局部变量表所需的内存空间在编译期间分配完成,所以当进入一个方法时,需要在帧中分配多大的局部变量空间是完全确定的(除了long和double类型的数据会占用2个局部变量空间外,其他基本数据类型仅占用1个局部变量空间),在方法运行期间并不会改变局部变量表的大小。如果线程请求的栈深度大于虚拟机的规定,将抛出StackOverFlowError异常;如果虚拟机栈动态扩展时无法申请到足够的内存空间,将会抛出OutOfMemoryError异常。

本地方法栈:它与虚拟机栈所发挥的作用相似,区别就是虚拟机栈为java方法服务,而本地方法栈为Native()方法服务,抛出异常痛上。

java堆:堆(Heap)是java虚拟机所管理内存的内存中最大的一块。java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,存放对象实例。当Heap没有内存可以完成实例分配,而且堆也无法再扩展时,将会抛出OutOfMemoryError异常

方法区:与java堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量和即时编译器编译后的代码等数据。虽然java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它有一个别名Non-Heap(非堆),提醒读者将它与java区分开。java虚拟机堆方法区的限制非常宽松,除了和java堆一样不需要连续的内存空间和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常。

此外,还有一个特殊区域——运行时常量池(Runtime Const Pool)是方法区的一部分。除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。另外一个重要特征是具有动态性,java语言并不要求常量一定只有编译器才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用的比较多的便是String类中Intern()方法。

对象的创建

当虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,如果没有,那必须先执行相应的类加载过程,类加载检查通过后,接下来就虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成便可完全确定,为对象分配空间的任务等同于把一块确定大小的内存从java队中划分出来,内存分配完成以后,虚拟机需要将分配到的内存空间都初始化0值(不包括对象头)(这一步操作保证了对象的实例字段在java代码中可以不赋初始值就直接使用),接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例,在上面的工作都完成以后,从虚拟机的视角来看,一个新的对象已经产生了,但从java程序的视角来看,对象创建才刚刚开始——<init>方法还没有执行,所有的字段都为0.

对象的内存布局

在HotSpot虚拟机中,对象在内存中的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

对象头:包括两部分信息,一是用于存储对象自身的运行时数据,如哈希码、GC分代年龄等,官方称为“Mark Word”。二是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例,如果对象是一个数组,那对象头中还必须有一块记录数组长度的数据。

实例数据:对象真正有效的信息,也是在程序代码中所定义的各种类型的字段内容。无论是来自父类还是子类,都需要记起来。这部分的存储顺序会受到虚拟机分配策略参数(FieldsAllocationStyle)和字段在Java源码中定义顺序的影响。

对齐填充:占位符,并非必然存在,没有特别的含义。

对象的访问定位

java程序需要通过栈上的reference数据来操作堆上的具体对象。java虚拟机规范中只规定reference类型只是一个指向对象的引用,并没有规定这个引用应该通过何种方式定位、访问堆中的对象的具体位置,所以对象的访问也是取决于虚拟机实现而定的。目前主流的访问方式时使用句柄和直接指针两种。

如果使用句柄访问的话,java堆中就会划分出一块内存来作为句柄池,reference类型中存储的就是对象的句柄类型,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。优点是句柄地址稳定,对象被移动后,只需改变句柄中的实例数据指针,而reference本身不需要修改。

如果使用直接指针访问,那么java堆对象的布局就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。优点是速度更快。

关于学习java虚拟机的知识整理一:jvm内存区域的更多相关文章

  1. Java虚拟机(一):JVM内存结构

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

  2. Java虚拟机(二):JVM内存模型

    所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问 ...

  3. 《深入理解Java虚拟机》之(一、内存区域)

    一.java的体系构成: Java的技术体系主要由支撑java程序运行的虚拟机.提供各种开发领域接口支持的java api.java编程语言及许多第三方java框架(如Spring .Struts等) ...

  4. 深入理解Java虚拟机之读书笔记一 自动内存管理机制

    一.运行时数据区域 1.程序计数器是线程的私有空间,每个线程都有.针对线程执行的是Java代码还是Native代码有两种取值,Java代码时:虚拟机字节码指令的地址:Native代码时:计数值为Und ...

  5. java部分基础知识整理----百度脑图版

    近期发现,通过百度脑图可以很好的归纳总结和整理知识点,本着学习和复习的目的,梳理了一下java部分的知识点,不定期更新,若有不恰之处,请指正,谢谢! 脑图链接如下:java部分基础知识整理----百度 ...

  6. Java虚拟机 - 结构原理与运行时数据区域

    http://liuwangshu.cn/java/jvm/1-runtime-data-area.html 前言 本来计划要写Android内存优化的,觉得有必要在此之前介绍一下Java虚拟机的相关 ...

  7. Java虚拟机------JVM内存区域

    JVM内存区域运行时数据区域分为两种: JVM内存区域 运行时数据区域分为两种: 线程隔离的数据区: 程序计数器 Java虚拟机栈 本地方法栈 所有线程程共享的数据区: Java堆 方法区 JVM 内 ...

  8. 深入理解java:1.3.1 JVM内存区域的划分(运行时数据区)

    学习Java GC机制,可以帮助我们在日常工作中 排查各种内存溢出或泄露问题,解决性能瓶颈,达到更高的并发量,写出更高效的程序. 我们将从4个方面学习Java GC机制, 1,内存是如何分配的: 2, ...

  9. JVM基础知识(1)-JVM内存区域与内存溢出

    JVM基础知识(1)-JVM内存区域与内存溢出 0. 目录 什么是JVM 运行时数据区域 HotSpot虚拟机对象探秘 OutOfMemoryError异常 1. 什么是JVM 1.1. 什么是JVM ...

随机推荐

  1. NLP(二十一)人物关系抽取的一次实战

      去年,笔者写过一篇文章利用关系抽取构建知识图谱的一次尝试,试图用现在的深度学习办法去做开放领域的关系抽取,但是遗憾的是,目前在开放领域的关系抽取,还没有成熟的解决方案和模型.当时的文章仅作为笔者的 ...

  2. Apache开启GZIP 压缩网页

    首先我们先了解Apache Gzip的相关资料. 一.gzip介绍 Gzip是一种流行的文件压缩算法,现在的应用十分广泛,尤其是在Linux平台.当应用Gzip压缩到一个纯文本文件时,效果是非常明显的 ...

  3. 11-HTTP请求协议

    今日知识 1. http 2. Tomcat使用 3. 知识总结 HTTP 1. 概念:Hyper Text Transfer Protocol * 传输协议:定义了,客户端和服务器通信时,发送的数据 ...

  4. js+css页面横屏

    <!DOCTYPE html> <html lang='zh'> <head> <meta charset="utf-8" /> & ...

  5. VFP执行 SQL Server 储存过程示例

    PUBLIC errvalPUBLIC errmsgPUBLIC handleerrval=0errmsg=' ' *Sql Server 连接参数sourcename= 'test'user= 's ...

  6. oracle数据库重要的查询语句

    查看所有数据文件(dbf文件)的存放位置 SQL> select name from v$datafile; 标红色的为默认表空间文件 SQL> select name from v$da ...

  7. macos常用命令备查

    常用命令 open . : 命令行打开文件夹 文件编辑 ps: 从一般模式进编辑模式,只需按i.I.a.A.o.O.r和R中某个键即可.当进入编辑模式时,在屏幕尾部会显示INSERT或REPLACE字 ...

  8. vs工程配置eslint检测环境

    vs工程打开一个js文件,会提示 "No ESLint configuration (e.g .eslintrc) found for file ......." 或 " ...

  9. Arm开发板+Qt学习之路-multiple definition of

    问题描述:在一个头文件a.h中定义一些变量x,在其他.c文件中(b.c,c.c)要用到.用一般的全局变量的方法,编译时总是提示error:multiple definition of x 问题分析:o ...

  10. Oracle Linux下安装Oracle11gR2

    Linux上Oracle11g R2安装及配置 一. 安装环境准备 1.  环境说明 Linux服务器系统:Oracle Linux Release 6 Update 2 (64bit),先安装好. ...