热门标签 | 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使用指针访问.

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

致词,感谢.



推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 从高级程序员到CTO的4次能力跃迁!如何选择适合的技术负责人?
    本文讲解了从高级程序员到CTO的4次能力跃迁,以及如何选择适合的技术负责人。在初创期、发展期、成熟期的每个阶段,创业公司需要不同级别的技术负责人来实现复杂功能、解决技术难题、提高交付效率和质量。高级程序员的职责是实现复杂功能、编写核心代码、处理线上bug、解决技术难题。而技术经理则需要提高交付效率和质量。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
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社区 版权所有