本篇文章给大家带来的内容是关于什么是堆?什么是方法区?JVM内存模型中堆与方法区的介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

一、堆(Heap)

1.1.什么是堆

堆是用于存放对象的内存区域。因此,它是垃圾收集器(GC)管理的主要目标。其具有以下特点:

  • 堆在逻辑上划分为“新生代”和“老年代”。由于JAVA中的对象大部分是朝生夕灭,还有一小部分能够长期的驻留在内存中,为了对这两种对象进行最有效的回收,将堆划分为新生代和老年代,并且执行不同的回收策略。不同的垃圾收集器对这2个逻辑区域的回收机制不尽相同,在后续的章节中我们将详细的讲解。
  • 堆占用的内存并不要求物理连续,只需要逻辑连续即可。
  • 堆一般实现成可扩展内存大小,使用“-Xms”与“-Xmx”控制堆的最小与最大内存,扩展动作交由虚拟机执行。但由于该行为比较消耗性能,因此一般将堆的最大最小内存设为相等。
  • 堆是所有线程共享的内存区域,因此每个线程都可以拿到堆上的同一个对象。
  • 堆的生命周期是随着虚拟机的启动而创建。

1.2.堆异常

当堆无法分配对象内存且无法再扩展时,会抛出OutOfMemoryError异常。

一般来说,堆无法分配对象时会进行一次GC,如果GC后仍然无法分配对象,才会报内存耗尽的错误。可以通过不断生成新的对象但不释放引用来模拟这种情形:

/*** java堆溢出demo* JVM参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError* Created by chenjunyi on 2018/4/25.*/
public class HeapOOM {static class OOMObject {}public static void main(String[] args) {List<OOMObject> list = new ArrayList<>();//不断创建新对象,使得Heap溢出while (true) {list.add(new OOMObject());}}}

上述代码中对象不断的被创建而不进行引用释放,导致GC无法回收堆内存,最终OutOfMemoryError,错误信息:

java.lang.OutOfMemoryError: Java heap space

二、方法区(Method Area)

2.1.什么是方法区

方法区,也称非堆(Non-Heap),又是一个被线程共享的内存区域。其中主要存储加载的类字节码、class/method/field等元数据对象、static-final常量、static变量、jit编译器编译后的代码等数据,。另外,方法区包含了一个特殊的区域“运行时常量池”,它们的关系如下图所示:

(1)加载的类字节码:要使用一个类,首先需要将其字节码加载到JVM的内存中。至于类的字节码来源,可以多种多样,如.class文件、网络传输、或cglib字节码框架直接生成。
(2)class/method/field等元数据对象:字节码加载之后,JVM会根据其中的内容,为这个类生成Class/Method/Field等对象,它们用于描述一个类,通常在反射中用的比较多。不同于存储在堆中的java实例对象,这两种对象存储在方法区中。
(3)static-final常量、static变量:对于这两种类型的类成员,JVM会在方法区为它们创建一份数据,因此同一个类的static修饰的类成员只有一份;
(4)jit编译器的编译结果:以hotspot虚拟机为例,其在运行时会使用JIT即时编译器对热点代码进行优化,优化方式为将字节码编译成机器码。通常情况下,JVM使用“解释执行”的方式执行字节码,即JVM在读取到一个字节码指令时,会将其按照预先定好的规则执行栈操作,而栈操作会进一步映射为底层的机器操作;通过JIT编译后,执行的机器码会直接和底层机器打交道。如下图所示:

2.2.运行时常量池

在2.1小节中,我们了解到类的字节码在加载时会被解析并生成不同的东西存入方法区。类的字节码中不仅包含了类的版本、字段、方法、接口等描述信息,还包含了一个常量池。常量池用于存放在字节码中使用到的所有字面量和符号引用(如字符串字面量),在类加载时,它们进入方法区的运行时常量池存放。

运行时常量池是方法区中一个比较特殊的部分,具备动态性,也就是说,除了类加载时将常量池写入其中,java程序运行期间也可以向其中写入常量:

// 使用StringBuilder在堆上创建字符串abc,再使用intern将其放入运行时常量池
String str = new StringBuilder("abc");
str.intern();
// 直接使用字符串字面量xyz,其被放入运行时常量池
String str2 = "xyz";

2.3.方法区的实现

方法区的实现,虚拟机规范中并未明确规定,目前有2种比较主流的实现方式:

(1)HotSpot虚拟机1.7-:在JDK1.6及之前版本,HotSpot使用“永久代(permanent generation)”的概念作为实现,即将GC分代收集扩展至方法区。这种实现比较偷懒,可以不必为方法区编写专门的内存管理,但带来的后果是容易碰到内存溢出的问题(因为永久代有-XX:MaxPermSize的上限)。在JDK1.7+之后,HotSpot逐渐改变方法区的实现方式,如1.7版本移除了方法区中的字符串常量池。

(2)HotSpot虚拟机1.8+:1.8版本中移除了方法区并使用metaspace(元数据空间)作为替代实现。metaspace占用系统内存,也就是说,只要不碰触到系统内存上限,方法区会有足够的内存空间。但这不意味着我们不对方法区进行限制,如果方法区无限膨胀,最终会导致系统崩溃。

我们思考一个问题,为什么使用“永久代”并将GC分代收集扩展至方法区这种实现方式不好,会导致OOM?首先要明白方法区的内存回收目标是什么,方法区存储了类的元数据信息和各种常量,它的内存回收目标理应当是对这些类型的卸载和常量的回收。但由于这些数据被类的实例引用,卸载条件变得复杂且严格,回收不当会导致堆中的类实例失去元数据信息和常量信息。因此,回收方法区内存不是一件简单高效的事情,往往GC在做无用功。另外随着应用规模的变大,各种框架的引入,尤其是使用了字节码生成技术的框架,会导致方法区内存占用越来越大,最终OOM。

2.4.方法区异常

在2.3一节中,我们了解到方法区的2种实现方式最终都会有一个最大值上限,因此若方法区(含运行时常量池)占用内存到达其最大值,且无法再申请到内存时,便会抛出OutOfMemoryError。

在下面的例子中,我们将使用cglib字节码生成框架不断生成新的类,最终使方法区内存占用满,抛出OutOfMemoryError:

/*** java方法区溢出OutOfMemoryError(JVM参数适用于JDK1.6之前,借助CGLIB)* JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M* Created by chenjunyi on 2018/4/26.*/
public class JavaMethodAreaOOM {public static void main(String[] args) {while (true) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OOMObject.class);enhancer.setUseCache(false);enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(objects, args));enhancer.create();}}static class OOMObject {}}

报错信息为:

Caused by: java.lang.OutOfMemoryError: PermGen spaceat java.lang.ClassLoader.defineClass1(Native Method)···

其实,在日常开发中,不仅仅使CGlib字节码生成框架会产生大量的class信息,动态语言、JSP、基于OSGI的应用都会在方法区额外产生大量的类信息。

什么是堆?什么是方法区?JVM内存模型中堆与方法区的介绍相关推荐

  1. CPU中的“程序计数器”和JVM内存模型中的“程序计数器”

    在理解JVM内存模型中的"程序计数器"时,可能会与CPU中的"程序计数器"混淆. CPU中的"程序计数器"属于硬件层面,如下图中的PC: J ...

  2. JVM(Java虚拟机)详解(JVM 内存模型、堆、GC、直接内存、性能调优)

    JVM(Java虚拟机) JVM 内存模型 结构图 jdk1.8 结构图(极简) jdk1.8 结构图(简单) JVM(Java虚拟机): 是一个抽象的计算模型. 如同一台真实的机器,它有自己的指令集 ...

  3. JVM 内存模型:方法区(Method Area)

    1. 前言 最近在研究Java语言底层基础知识,发现对于JVM 内存模型理解不够深入.笔者突发奇想深入理解JVM内存模型,特在此介绍详细介绍一下JVM内存模型中的方法区.看似名称叫做方法区,其实不然. ...

  4. java 内存模型面试_Java面试- JVM 内存模型讲解

    经常有人会有这么一个疑惑,难道 Java 开发就一定要懂得 JVM 的原理吗?我不懂 JVM ,但我照样可以开发.确实,但如果懂得了 JVM ,可以让你在技术的这条路上走的更远一些. JVM 的重要性 ...

  5. java实现初始化三角形数组_Java 数组、多维数组,动态、静态初始化,数组JVM内存模型分析...

    Java 数组.多维数组,动态.静态初始化,数组JVM内存模型分析 什么是数组 所谓数组,是具有相同数据类型的若干变量或者数据按照一定排序规则组合起来的一种数据存储格式.数组中的数据称为数组元素,我们 ...

  6. JVM内存区域(运行时数据区)划分

    前言: 我们每天都在编写Java代码,编译,执行.很多人已经知道Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文 ...

  7. @JVM内存模型(运行时数据区)

    前言 说到Java内存区域,可能很多人第一反应是"堆栈".首先堆栈不是一个概念,而是两个概念,堆和栈是两块不同的内存区域,简单理解的话,堆是用来存放对象而栈是用来执行程序的.对于J ...

  8. 面试回答,JVM内存模型/内存空间:运行时数据区

    发布于个人公众号,打开微信,搜索MelodyJerry即可 本文由作者原文 [JVM|内存模型] Java虚拟机的内存模型?也就这7个而已 修改而来,可点击左下角阅读原文. JVM内存模型/内存空间 ...

  9. jvm内存溢出区域和排查方法

    目录 1.堆溢出 2.栈溢出 3.方法区和运行时常量池溢出 4.本机直接内存溢出 首先我们需要掌握什么是内存溢出和内存泄漏 内存泄漏:即声明的对象无法被回收,一直存在于内存中,使得占用的内存就像被泄漏 ...

  10. java中栈和堆都存哪些东西_java中栈内存与堆内存(JVM内存模型)

    java中栈内存与堆内存(JVM内存模型) Java中堆内存和栈内存详解1 和 Java中堆内存和栈内存详解2 都粗略讲解了栈内存和堆内存的区别,以及代码中哪些变量存储在堆中.哪些存储在栈中.内存中的 ...

最新文章

  1. scrollWidth,clientWidth,offsetWidth的区别
  2. linux设置进程优先级,Linux线程属性及优先级设置
  3. 再谈 HBase 八大应用场景
  4. linux 实时 网口 速率_linux 下查看网卡工作速率-阿里云开发者社区
  5. Android组件系列-----Activity保存状态
  6. [HTML/CSS]浮动的那点事儿
  7. ecu的c语言编程,ecu中的程序是如何编写的
  8. 如何安装2018matlab,MATLAB 2018a软件安装教程
  9. java ipv6校验_Java对IPv6的支持详解:支持情况、相关API、演示代码等
  10. Foundry教程:ERC-20代币智能合约从编写到部署全流程开发
  11. Windows Server 2012 IPAM的管理
  12. 如何离线安装所有依赖包
  13. 面对一切,我们要坦然
  14. 什么是字节码?采用字节码的好处是什么?
  15. 学会做笔记-子弹笔记学习概要三
  16. 东南大学计算机学院推免名单,东南大学计算机软件初试全书.pdf
  17. python爬取微博热搜显示到折线图_微博热搜榜前20信息数据爬取进行数据分析与可视化...
  18. 用计算机弹出草木,2011-06-06 2010~2011年北京市石景山区普通高中信息技术《信息技术基础》《人工智能初步》—笔试试题(定稿...
  19. 怎么把mkv格式改成mp4?不妨试试这几种方法吧!
  20. 看《反恐24小时》的得到的教训与魔鬼词典

热门文章

  1. 投入产出比增长2倍以上!银泰抛弃传统数据库转投阿里云PolarDB
  2. 【回归预测】基于matlab灰狼算法优化ELMAN神经网络回归预测【含Matlab源码 1782期】
  3. 毕设题目:Matlab疾病识别与分类
  4. 【TSP】基于matlab遗传和模拟退火算法求解旅行商问题【含Matlab源码 696期】
  5. 机器学习 神经网络 神经元_神经网络如何学习?
  6. python窗口怎么显示,如何使用Python在没有窗口的屏幕上显示文本
  7. pythontab_PythonTab 中文网简介
  8. 允许使用抽象类类型 isearchboxinfo 的对象_Java面向对象之final、abstract抽象、和变量生命周期...
  9. c#调用java的webservice方法,C# 调用 Java WebService | 思考的极致
  10. 店宝宝电脑版_母婴店主干货分享:母婴店利润究竟有多大?