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

JVM开篇Java内存区域与内存溢出异常

Java虚拟机在运行时会将内存划分为若干区域,我们经常会说堆、栈,栈中存放的是基础类型和对象引用地址,堆中存放的是对象。那么实际上JVM运行时到底将内存划分了多少区域,这些区域都会存储什么数据以及如何进行回收?

JVM开篇---Java内存区域与内存溢出异常

如上图所示,JVM将内存划分为五个区域。

程序计数器:是线程隔离的一块较小的内存区域,因为java多线程是并发的,即轮轮流的切换线程并且分配处理器来执行的一种方式,所以每个线程都需要记录自己所执行的位置,所以在程序计数器内为每个线程都要保存一份独立的计数。程序计数器可以理解为程序执行到的字节码位置,一般来讲程序的执行就是改变这个计数值。如果当前执行的是Native方法,则这个计数器值为空(undefined)。该内存区域是唯一一块没有规定任何OutOfMemoryError的区域。

Java虚拟机栈:也是线程隔离的一块内存区域,与线程的生命周期相同。它描述了java方法执行的内存模型:每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等。每一个方法的调用到执行完成,对应着栈的入栈与出栈操作。我们一开始说的存放基础类型和对象引用地址的栈就是指的虚拟机栈中的局部变量表。局部变量表里就存放了boolean、byte、int、long、float、double、对象的引用和returnAddress类型,其中long和double占用两个局部变量空间,其余都占用一个。局部变量表在编译器就已经确定大小,并分配内存空间,在运行过程中是不会改变的。returnAddress没有看太明白。这个区域有两种异常:一个是请求的栈深度超过了虚拟机所允许的深度,会报出***Error;一个是如果虚拟机可以动态扩展虚拟机栈,当无法申请更多内存时,会报OutOfMemoryError。

本地方法栈:与java虚拟机栈的区别就是,本地方法栈执行本地方法使用。

java堆:堆是被所有线程共享的一块最大的内存,所有的对象实例和数组都在堆上分配内存。此话现在不绝对,后续会说到。为了更快地进行垃圾回收,一般现在会将堆分代,新生代和老年代,又可以细化为eden区、from区、to区、老年代。

方法区:线程共享的内存,存储已经加载的类的信息、常量、静态变量、即时编译器编译后的代码等。运行时常量是方法区的一部分,就是我们所说的string所存放的地方。在之前的hotspot虚拟机上,方法区也可以叫做永久代,我们经常会遇到java.lang.OutOfMemoryError: PermGen space 这个就代表方法区溢出。因为将运行时常量、类信息存放在方法区,会经常导致内存溢出,并且永久代是hotspot独有的概念,所以从jdk1.7开始就逐渐的取消了永久代的概念。到jdk1.8已经完全取消,类信息、stirng和静态变量都将会被移到堆和本地内存中。永久代由MetaSpace所取代,保存到本地内存中,MetaSpace思想就是类和他的元数据的生命周期和他的类加载器的生命周期一致,每个类加载器的存储区都叫做一个元空间,所有的元空间组合到一起。我们再大量的创建string对象导致内存溢出,不会再是PermGen space了,而是变成了heap space溢出,因为stirng常量池已经移到了堆中。要想使MetaSpace溢出,需要创建新的类,导致其溢出。

新的设置MetaSpace的参数有:

-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
  -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。
  除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
  -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
  -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

以上就是JVM的基本运行时内存分配情况


推荐阅读
  • C#按值复制数组我有一个类型化的数组MyType[]types;我想制作这个数组的独立副本。我试过这个MyType[]types2newMyType[types.Length];t ... [详细]
  • 开发笔记:Java多线程深度探索
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java多线程深度探索相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 2022年Python面试题一.Python基础二.企业面试题结束语🥇🥇🥇✅作者简介:大家好我是编程IDὌ ... [详细]
  • java内存模型浅析_浅析Java内存模型
    在并发编程中,需要处理两个关键问题:线程之间如何通信以及线程之间如何同步。通信是指线程之间以何种机制来交换信息。同步是指程序中用于控制不同线程间操作发生 ... [详细]
  • 无需人类知识,DeepMind新一代围棋程序AlphaGo Zero再次登上Nature
    选自DeepMind机器之心编译在今年五月击败柯洁之后,AlphaGo并没有停止自己的发展。昨天,DeepMind在《自然》杂志上发表了一篇论文 ... [详细]
  • ———Java培训、Android培训、iOS培训、.Net培训、期待与您交流!———一、引用计数器每个OC对象都有自己的引用计数器,表示“对象被引用 ... [详细]
  • 每日一书丨AI圣经《深度学习》作者斩获2018年图灵奖
    2019年3月27日——ACM宣布,深度学习之父YoshuaBengio,YannLeCun,以及GeoffreyHinton获得了2018年的图灵奖, ... [详细]
  • 成都万有算力(广州算力网络科技有限公司)
    在同期举办的第十三届天翼智能生态高峰论坛上,中国电信正式发布《中国电信AI+计划》。但从目前来看,后者的影响早已反过来远大于受置疑的前者。包括自由的金针菇、单纯的长颈鹿在内多位专家 ... [详细]
  • 在Java程序中使用多线程要比在C或C++中容易得多,这是因为Java编程语言提供了语言级的支持。为什么会排队等待?下面的这个简单的Java程序完成四项不相关的任 ... [详细]
  • 【JVM技术专题】深入分析CG管理和原理查缺补漏「番外篇」
    前提概要本文主要针对HotspotVM中“CMSParNew”组合的一些使用场景进行总结。自Sun发布Java语言以来,开始使用GC技术来进行内存自动管理࿰ ... [详细]
  • 内容多有疏漏,有问题欢迎提出目录java内存模型的概念原子性(Atomicity)可见性(Visibility࿰ ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
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社区 版权所有