前言:Java与C++之间有一堵高墙,主要是有内存动态分配和垃圾收集技术组成的。墙外的人想要进来,墙内的人想要出去。

  一、运行时数据区域

    JVM在执行Java程序时,会将其管理的内存划分为若干个不同的数据区域。

     1、是程序计数器,一个处理器一般只会执行一条线程的指令。为了线程切换后恢复到正确的执行位置,每一条线程都需要一个独立的程序计数器,每一个计数器互相不影响,独立存储,最重要的一点事,此类内存区域属于“线程私有”的内存。

    2、接下来介绍,Java虚拟机栈也是线程私有的,虚拟机栈指的是Java方法执行的线程内存模型。经常有人将Java内存区域笼统的划分为“堆内存”和“栈内存”。这里的“栈内存”指的是Java虚拟机栈,但是确切的说是,虚拟机栈中的局部变量表部分。局部变量表存储了各种基本的数据类型,存储空间以局部变量槽表示,关于局部变量槽所占用的比特数量,有虚拟机决定。

    3、其次是本地方法栈:为虚拟机用到的本地方法服务,有些虚拟机会将本地方法栈和虚拟方法栈合并(HotSpot:关于它的解释,见以前的博客)。

    4、Java堆:Java堆是虚拟机所管理的内存中的最大的一部分,被所有线程所共享,同时也是垃圾收集器管理的内存区域,从分配内存的角度来看,Java堆可以分出多个线程私有的分配缓冲区,来提高对象分配时的效率。PS:根据规定,Java堆在物理上可以不连续,但是在逻辑上是连续的。

    5、方法区:是一个线程共享的内存区域,用来存储已经被虚拟机加载的类型信息、常量、静态变量等数据。

    6、运行时常量池:方法区的一部分,Class文件中除了常见的描述信息外,还有一项信息是常量池表,用来存放编译期生成的高中字面量和符号引用,常量池表的内容在类引用之后存放到方法区中的运行时常量池中。另外一个特征是动态性,可以在运行期间将新的常量加入池中。

    7、直接内存:使用native函数库直接分配堆外内存,通过存放在Java堆中的对象作为这一部分内存的引用进行操作。

  二、HotSpot虚拟机对象探秘

    在第一部分,学习了内存存放什么,但是对于如何创建以及如何访问等,存在着盲区,这里采用最常见的虚拟机Hotspot和最常用的内存区域Java堆。来深入探讨一些虚拟机内部的神秘世界。

    2.1、对象的创建

      1、当遇到new命令时,检查指令的参数是否能在常量池中正确定位符号的引用,检查符号代表的类是否被加载、解析和初始化过。如果没有执行操作2。

      2、类加载检查通过后,为新生对象分配内存(大小确定),Java堆中的内存必定存在已经分配和未被分配的,所以分配方式引入“指针碰撞”的方式进行分配内存[Java堆内存是规整的],如果不规整的话,需要采用“空闲列表”的方式,来分配内存。

      3、除了划分可用空间之外,对象在虚拟机创建的行为是频繁的,经常发生“线程安全”问题,解决方法:1、保证分配空间的原子性。2、预先分配内存,此方式为“本地线程分配缓冲”:哪家线程要分配内存,就在哪家的本地缓冲区中分配,只有这一次的本地缓冲区用完之后,采用分配新的,同时进行同步锁定。

      4、分配到的内存空间初始化为零值,这样的操作,对应到Java代码中为:不用赋予初始值就可以使用

      5、所有的信息都要存储到对象头中。

      6、虽然上述操作介绍完了,但是仅此还是不够的。对象构建需要的其他资源也没有弄好。  

    2.2、对象的内存布局

      HotSpot虚拟机中,对象在堆内存中的存储布局主要分为三个部分:对象头、实例数据、对齐填充。

      首先介绍一下对象头,对象头主要分为两部分,第一部分是用于存储对象自身的运行时数据,包括各类的标识元数据信息,为了更好的存储数据,所以将此设计为动态定义的数据结构。第二部分是类型指针,也就是对象指向它的类型元数据的指针,查找对象的元数据信息并不一定经过对象本身。

      实例数据:用来存储对象的真正有效的信息,也就是我们在程序代码中定义的各种类型的字段内容。

      对齐填充:仅仅是占位符的作用,因为自动内存管理系统要求对象的起始地址必须是8字节的整数倍,所以,对于对象实例数据没有对齐的部分,就需要通过填充来对齐。

    2.3、对象的访问定位

      因为在Java程序中没有被定义,所以具体的访问方式需要在虚拟机中去实现,主流的访问方式有使用句柄和直接指针两种。

      1、使用句柄:这个像是引入了“中间商”,Java堆中划出一块内存来当做句柄池。

      2、使用直接访问:reference存储的直接就是对象地址。

      两者只能说是各有优劣,句柄最大的好处是,当对象被移动是,只会修改句柄中的实例数据指针,而reference本身不需要修改。直接指针最大的优点就是访问速度更快。本文以HotSpot为主,它采用的是直接指针访问的方式,但是如果从整个软件开发的范围来看,使用句柄来访问显得更加的优秀。

  三、实战:OutOfMemoryError 异常

    1、Java堆溢出:这种异常方式是最为常见的内存溢出情况,解决方法在于:通过内存映像分析工具 对Dump出来的堆转储快照进行分析。存在内存泄漏内存溢出两种。

    2、虚拟机栈和本地方法栈溢出:

    3、方法区和运行时常量池溢出:运行时常量池是方法区的一部分.

    4、本地直接内存溢出‘:直接内存的大小可以通过参数来制定。

Java虚拟机(JVM):第二幕:自动内存管理 - Java内存区域与内存溢出异常的更多相关文章

  1. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  2. [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义

    前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine  ,既然是虚拟机, ...

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

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

  4. java虚拟机 jvm 出入java栈 栈空间内存分配

    java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...

  5. 如何设置Java虚拟机JVM启动内存参数

    Tomcat默认的Java虚拟机JVM启动内存参数大约只有64MB或者128MB,非常小,远远没有利用现在服务器的强大内存,所以要设置Java虚拟机JVM启动内存参数.具体设置方法为: Tomcat修 ...

  6. 深入理解java虚拟机_第二章_读书笔记

    1.本章内容目录: 概述 运行时数据区域 程序计数器 java虚拟机栈 本地方法栈 java堆 方法区 运行时常量池 直接内存 HotSpot虚拟机对象探秘 对象的创建 对象的内存布局 对象的访问定位 ...

  7. Java虚拟机(JVM)知多少

    本文大量参考:https://www.cnblogs.com/lfs2640666960/p/9297176.html 概述 JVM是JRE的一部分.它是一个虚构出来的计算机,是通过在实际的计算机上仿 ...

  8. 深入理解java虚拟机JVM(下)

    深入理解java虚拟机JVM(下) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...

  9. Java虚拟机JVM相关知识整理

    Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系 ...

  10. 深入理解java虚拟机JVM(上)

    深入理解java虚拟机JVM(上) 链接:https://pan.baidu.com/s/1c6pZjLeMQqc9t-OXvUM66w 提取码:uwak 复制这段内容后打开百度网盘手机App,操作更 ...

随机推荐

  1. 手写数字识别系统Python+CNN卷积神经网络算法【完整代码】

    一.介绍 手写数字识别系统,使用Python语言,基于TensorFlow搭建CNN卷积神经网络算法对数据集进行训练,最后得到模型,并基于FLask搭建网页端界面,基于Pyqt5搭建桌面端可视化界面. ...

  2. C++面试八股文:知道std::unordered_set/std::unordered_map吗?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第27面: 面试官:知道std::unordered_set/std::unordered_map吗? 二师兄:知道.两者都是C++11引入的新容器, ...

  3. 【FAQ】关于CP反馈的联运应用的常见结算问题小结

    问题一:为什么在"我的账户">>"收益"里面的金额和支付报表中的金额对不上 ? 关于联运类应用付费产品在华为平台上结算问题,您可以详细参考一下&qu ...

  4. win10系统网络图标变成一个地球模型并且无法连上网络

    最近在家远程办公,但是遇到个很棘手的问题,电脑突然连不上无线网络了.... 无线网络图标变成地球模型如下:

  5. 了解O2OA(翱途)开发平台中的VIP应用

    使用O2OA(翱途)开发平台可以非常方便地进行项目的业务需求开发与实施,O2OA(翱途)开发平台并不限制实现的系统类型,所以能实现的系统很多,最终呈现的项目成果也是多样性的,可能是OA系统,可能是人力 ...

  6. Python数据分析易错知识点归纳(三):Pandas

    三.pandas 不带括号的基本属性 df.index # 结果是一个Index对象, 可以使用等号重新赋值,如: df.index = ['a', 'b', 'c'] df.columns # 结果 ...

  7. async/await初学者指南

    JavaScript中的async和await关键字提供了一种现代语法,帮助我们处理异步操作.在本教程中,我们将深入研究如何使用async/await来掌控JavaScript程序中的流程控制. 总览 ...

  8. 【技术实战】Vue技术实战【三】

    需求实战一 效果展示 代码展示 <template> <div style="display: flex;"> <div style="di ...

  9. (转)IBM Appscan9.0.3安全扫描简单安装、使用以及高危漏洞修复

    最近手上负责一个的项目要进行等保评测.请的第三方公司采用IBM Security AppScan Standard对项目进行安全测试.测试报告高危漏洞主要包含sql注入.sql盲注.跨站点脚本编制如下 ...

  10. c++中unique_ptr 的使用和理解

    unique_ptr 的使用 std::unique_ptr是c++11起引入的智能指针,为什么必须要在c++11起才有该特性,主要还是c++11增加了move语义,否则无法对对象的所有权进行传递. ...