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

java占位符填充_Java内存区域与内存溢出异常

对于java程序员来说,虚拟机自动内存管理机制帮助javer们管理内存,不需要再deletefree,不容易出现内存泄漏和溢出问题,也正因为如此,一旦出现了泄露和溢出,如果不了解虚

对于java程序员来说,虚拟机自动内存管理机制帮助javer们管理内存,不需要再delete/free,不容易出现内存泄漏和溢出问题,也正因为如此,一旦出现了泄露和溢出,如果不了解虚拟机是如何使用内存的,那么排查将非常艰难.

一. 我们先来了解一下java内存的划分.
eb57b3552a5a587f1d5477c33ca788d7.png

由图可以看出,java内存划分分为两种类型,一种是所有线程共享的数据区,另一种是线程隔离的数据区.

程序计数器:

  1. 是内存中较小的一块空间,可以看作是当前线程所执行的字节码的行号指示器.
  2. 每个线程都有一个线程指示器,用于多线程切换时记录当前执行的行号.
  3. 当线程执行java方法时,计数器记录字节码的地址,如果正在执行Native方法,这个计数器值为空(Underfined)
  4. 此内存是唯一一个没有规定OutOfMemoryError情况的区域.
  5. 线程私有

java虚拟机栈:

  1. 每个方法在执行的时候都会创建一个栈帧,存储局部变量表,操作数栈,动态链接,方法出口等信息.一个方法从调用到执行完成的过程,就是一个栈帧在虚拟机栈中入栈到出栈的过程.
  2. 局部变量表存放了编译器可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double),对象引用和returnAddress类型.其中64位的long和double会占用2个局部变量空间,其余的数据只占用一个.
  3. 局部变量表所需的内存空间在编译器完成分配,当进入一个方法时,所需要的局部变量空间是完全确定的.在方法运行期间不会改变局部变量表的大小
  4. 本区域两种异常情况:线程请求栈深超过所允许的深度,抛出StackOverflowError异常;如果本区域可以动态扩展,并且无法申请到足够的内存,会抛出OutOfMemoryError异常.
  5. 线程私有

本地方法栈:

  1. 与虚拟机栈发挥的作用非常相似,不同的是本地方法栈为虚拟机使用到的Native方法服务.
  2. 虚拟机规范对本区域的语言,方式,数据结构没有强制规定,可以自由实现.
  3. Sun HotSpot虚拟机将本区域与虚拟机栈合二为一.
  4. 抛出异常同虚拟机栈
  5. 线程私有

java堆:

  1. java虚拟机管理的内存中最大的一块,也是GC工作的主要区域.
  2. 此内存存放对象实例(对象,数组),规范中规定所有对象实例都在这里分配内存.
  3. 栈上分配和标量替换是的规范不再绝对.
  4. java堆可以处于物理上不连续的内存空间中,只要逻辑连续即可.
  5. 线程共享

方法区:

  1. 用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据.
  2. 可以实现垃圾回收,但回收成果很小,hotSpot将方法区列为永久代,进行垃圾回收.
  3. java虚拟机规范将方法区描述为堆的一个逻辑部分,但却有另一个名字Non-Head(非堆)
  4. 无法满足内存分配的需求时,将抛出OutOfMemoryError异常.
  5. 线程共享

运行时常量池:

  1. 是方法区的一部分.
  2. 运行时常量池存放编译期生成的各种字面量和符号引用,这部分内容在类加载后进入方法区的运行期常量池存放.
  3. 运行时常量池具备动态性,并不要求只有编译器才能产生,运行期间可以将新的常量放入池中.
  4. 作为方法区的一部分,自然受到方法去内存限制,无法再申请内存时抛出OutOfMemoryError.

直接内存:

  1. 不是虚拟机运行时数据区的一部分,也不是虚拟机规范定义的内存区域,但被频繁使用,也会导致OutOfMemoryError出现.
  2. 直接内存不受java堆大小的限制.会受到本机总内存大小及处理器寻址空间的限制.
二. 下面来讲解各内存是如何创建,布局和访问的.首先讲解堆中内存的分配问题.

对象的创建:

  1. 虚拟机遇到new指令时,检查到常量池中能否定位一个类的符号引用,并检查这个符号引用代表的类是否已加载,解析和初始化过,如果没有,那必须先执行类的加载过程.
  2. 在类加载检查通过后,为新生对象分配内存.对象所需的内存大小已经完全确定,分配内存分为:指针碰撞和空闲列表两种方式.区别时java堆中内存空间是否规整决定方式.
  3. 划分内存空间需要注意并发问题.
  4. 划分空间后,内存空间初始化为零值(不包括对象头)
  5. 接下来,虚拟机对对象进行必要的整理,将这些信息存放到对象头中.已虚拟机角度看,对象创建已经完成.
  6. java程序上,开始执行初始化方法.对象创建完成.

对象的内存布局:

  1. 对象头(Header):对象头包含两部分信息,一部分:存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志等,这部分数据在31和64虚拟机中占32bit和64bit,官方称为"Mark Word";另一部分是:类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针确定这个对象是哪个类的实例.
  2. 实例数据(Instance Data):是对象真正存储的有效信息,也是程序代码中定义的各种类型的字段内容.
  3. 对齐填充(Padding):这部分并不是必然存在,也么有特别的含义,仅仅是占位符的作用.对象的大小必须是8的整数倍,这部分用来对齐.

对象的访问定位:

对象的访问通过栈上reference数据来操作堆上的具体对象,java虚拟机只规定了对象的引用,没有规定该如何去定位,这部分又虚拟机实现而定.主流方式有二

  1. 句柄访问:Java堆中会划分出一块内存来作为句柄池,reference中存储对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息.
  2. 直接指针访问:java堆对象的布局中就必须放置访问类型数据的相关信息,而reference中存储的直接就是地址.

两种方式各有优势.句柄访问好处是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不修改.

使用指针访问的好处是速度更快,节省了一次指针定位的时间开销.虚拟机Sun HotSpot使用指针访问.

本节内容到此结束,内容为书本知识的总结,切勿认为是抄袭.

致词,感谢.



推荐阅读
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • 本文深入解析了JDK 8中HashMap的源代码,重点探讨了put方法的工作机制及其内部参数的设定原理。HashMap允许键和值为null,但键为null的情况只能出现一次,因为null键在内部通过索引0进行存储。文章详细分析了capacity(容量)、size(大小)、loadFactor(加载因子)以及红黑树转换阈值的设定原则,帮助读者更好地理解HashMap的高效实现和性能优化策略。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • 本文介绍了Java中的com.sun.codemodel.JBlock._continue()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 深入解析:Synchronized 关键字在 Java 中对 int 和 Integer 对象的作用与影响
    深入探讨了 `Synchronized` 关键字在 Java 中对 `int` 和 `Integer` 对象的影响。尽管初看此题似乎简单,但其实质在于理解对象的概念。根据《Java编程思想》第二章的观点,一切皆为对象。本文详细分析了 `Synchronized` 关键字在不同数据类型上的作用机制,特别是对基本数据类型 `int` 和包装类 `Integer` 的区别处理,帮助读者深入理解 Java 中的同步机制及其在多线程环境中的应用。 ... [详细]
  • Coviam 实习软件工程师的工作体验与成长 ... [详细]
  • 在机器学习领域,深入探讨了概率论与数理统计的基础知识,特别是这些理论在数据挖掘中的应用。文章重点分析了偏差(Bias)与方差(Variance)之间的平衡问题,强调了方差反映了不同训练模型之间的差异,例如在K折交叉验证中,不同模型之间的性能差异显著。此外,还讨论了如何通过优化模型选择和参数调整来有效控制这一平衡,以提高模型的泛化能力。 ... [详细]
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 【问题】在Android开发中,当为EditText添加TextWatcher并实现onTextChanged方法时,会遇到一个问题:即使只对EditText进行一次修改(例如使用删除键删除一个字符),该方法也会被频繁触发。这不仅影响性能,还可能导致逻辑错误。本文将探讨这一问题的原因,并提供有效的解决方案,包括使用Handler或计时器来限制方法的调用频率,以及通过自定义TextWatcher来优化事件处理,从而提高应用的稳定性和用户体验。 ... [详细]
  • 如何使用 `org.apache.poi.openxml4j.opc.PackagePart` 类中的 `loadRelationships()` 方法及其代码示例详解 ... [详细]
  • 目前我有两张 BMP 图像文件 a.bmp 和 b.bmp,希望将它们按照以下方式进行融合:首先提取 a.bmp 的所有奇数行像素(如第 1、3、5 行),接着获取 b.bmp 的所有偶数行像素(如第 2、4、6 行)。最终目标是将这些行像素交替排列,生成一张新的图像。此过程需要确保像素顺序正确,并保持图像的整体结构和质量。 ... [详细]
  • Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战?
    Cosmos生态系统为何迅速崛起,波卡作为跨链巨头应如何应对挑战? ... [详细]
author-avatar
一二三
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有