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

如上图所示,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. linux下安装php的svn模块

    在php下为了方便使用svn命令,还是安装下php的svn扩展 首先确保机器上已经有lamp或lnmp环境,然后 >yum install subversion subversion-devel ...

  2. Django表单Form类对空值None的替换

    最近在写项目的时候用到Form,发现这个类什么都好,就是有些空值的默认赋值真是很不合我胃口. 查阅资料.官方文档后发现并没有设置该值的方式.于是,便开始了我的踩坑之路...... 不过现在完美解决了, ...

  3. LeetCode 684. Redundant Connection 冗余连接(C++/Java)

    题目: In this problem, a tree is an undirected graph that is connected and has no cycles. The given in ...

  4. step1:准备歌词之《前端开发是个啥》

    以下是给大家介绍前端开发的填词,曲子是李圣杰的<最近>,大家喜欢可以试试唱. 点赞关注超过100的平台,我后续上来发本人原唱视频(目前正在练习中...),另外大家觉得哪些词写得不好的,欢迎 ...

  5. 文件图片上传目录 禁止执行php

    apache配置上传目录禁止运行php的方法 导读: 禁止上传目录运行php等可执行文件可以从一定程度上增加网站的安全性, 禁止上传目录运行php的方法可以用.htaccess文件, 也可以直接在ap ...

  6. [Memcached]操作

    telnet连接memcached 查看端口是否可访问 # telnet 172.16.1.1 11211 Trying 172.16.1.1... Connected to 172.16.1.1. ...

  7. docker实战部署Javaweb项目

    一.部署环境说明 docker服务版本:version 18.09.0nginx服务版本:version: nginx/1.15.10redis服务版本:version: redis/5.0.3tom ...

  8. B树(B-树) 、B+树

    B树(B-树) 1.B-树(B树)的基本概念B-树中所有结点中孩子结点个数的最大值成为B-树的阶,通常用m表示,从查找效率考虑,一般要求m>=3.一棵m阶B-树或者是一棵空树,或者是满足以下条件 ...

  9. WinFrom 在Devexpress里用GridControl和DataNavigtor进行分页

    1,分页嘛先要有个SQL 程序才能写下去 先提供下SQL的思路,对于分页的SQL我之前帖子有介绍,就不一一介绍了 select top pageSize * --显示数量 from (select r ...

  10. 转载:字符编码简介 ASCII UTF-8 ISO8859-1

    字符编码简介 ASCII UTF-8 ISO8859-1 博客分类: 电脑综合知识 XP数据结构Windows  计算机中的一切都是以数字来表示的,字符同样如此.字符编码就是将字符集编码成为数字序列, ...