漫画:Java内存数据区域详解

https://github.com/TangBean

漫画由小猿编写创作

仔细看下面的思维导图,我们先来获取一个直观的认识,然后再一个一个详细分析!

总共也就这么 5 个区(直接内存不属于 JVM 运行时数据区的一部分),除了程序计数器其他的地方都有可能出现 OOM (OutOfMemoryError),其中像是程序计数器和两个栈(Java 虚拟机栈 & 本地方法栈)都是每个线程要有一个的,所以肯定是线程隔离的。而其他 2 个区就是线程共享的了,也就是说,如果有多个线程要同时访问这两个区的数据,是会出现线程安全问题的。接下来,我们将对这些区域进行详细的介绍。

程序计数器

  • 当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来确定下一条要执行的字节码指令的位置

  • 执行 Java 方法和 native 方法时的区别:

    • 执行 Java 方法时:记录虚拟机正在执行的字节码指令地址;

    • 执行 native 方法时:无定义;

  • 是 5 个区域中唯一不会出现 OOM 的区域。

Java 虚拟机栈

  • Java 方法执行的内存模型,每个方法执行的过程,就是它所对应的栈帧在虚拟机栈中入栈到出栈的过程;

  • 服务于 Java 方法;

  • 可能抛出的异常:

    • OutOfMemoryError(在虚拟机栈可以动态扩展的情况下,扩展时无法申请到足够的内存);

    • StackOverflowError(线程请求的栈深度 > 虚拟机所允许的深度);

  • 虚拟机参数设置:-Xss.

本地方法栈

  • 服务于 native 方法;

  • 可能抛出的异常:与 Java 虚拟机栈一样。

Java 堆

  • 唯一的目的:存放对象实例;

  • 垃圾收集器管理的主要区域;

  • 可以处于物理上不连续的内存空间中;

  • 可能抛出的异常:

    • OutOfMemoryError(堆中没有内存可以分配给新创建的实例,并且堆也无法再继续扩展了)。

  • 虚拟机参数设置:

    • 最大值:-Xmx

    • 最小值:-Xms

    • 两个参数设置成相同的值可避免堆自动扩展。

方法区

  • 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;

    • 类信息:即 Class 类,如类名、访问修饰符、常量池、字段描述、方法描述等。

  • 垃圾收集行为在此区域很少发生;

    • 不过也不能不清理,对于经常动态生成大量 Class 的应用,如 Spring 等,需要特别注意类的回收状况。

  • 运行时常量池也是方法区的一部分;

    • Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项是常量池,用于存放编译器生成的各种字面量(就是代码中定义的 static final 常量)和符号引用,这部分信息就存储在运行时常量池中。

  • 可能抛出的异常:

    • OutOfMemoryError(方法区无法满足内存分配需求时)。

直接内存

  • JDK 1.4 的 NIO 类可以使用 native 函数库直接分配堆外内存,这是一种基于通道与缓冲区的 I/O 方式,它在 Java 堆中存储一个 DirectByteBuffer 对象作为堆外内存的引用,这样就可以对堆外内存进行操作了。因为可以避免 Java 堆和 Native 堆之间来回复制数据,在一些场景可以带来显著的性能提高。

  • 虚拟机参数设置:-XX:MaxDirectMemorySize

    • 默认等于 Java 堆最大值,即 -Xmx 指定的值。

  • 将直接内存放在这里讲解的原因是它也可能会出现 OutOfMemoryError;

    • 服务器管理员在配置 JVM 参数时,会根据机器的实际内存设置 -Xmx 等信息,但经常会忽略直接内存(默认等于 -Xmx 设置值),这可能会使得各个内存区域的总和大于物理内存限制,从而导致动态扩展时出现 OOM。

今日话题

大家对于今天Java内存区域,有没有更深刻的理解呢?请在评论区留言和作者一起讨论!每日话题就是希望大家多交流,每个人都有在公众号发言的权力!希望你和我一起在这里成长!

点击「写留言」分享你的看法吧~

(0)

相关推荐

  • Java 虚拟机运行时数据区详解

    本文摘自深入理解 Java 虚拟机第三版 概述 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟 ...

  • 几种常见的内存溢出与解决办法

    引起内存溢出的原因有很多种,常见的有以下几种: 1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据: 2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收: 3.代码中存在死循环或循 ...

  • Java中的多态详解

    一.多态的概念 多态分为类的多态和方法的多态,类的多态就是一个类型可以有不同的表现形态,什么样的类型才会具备多态呢?只有被多个子类继承或者实现的父类才具备多态的特征,因为在运行期间可以根据具体的子类表 ...

  • Java并发之AQS详解

    一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)! 类如其名,抽象的队列式的同步器,AQ ...

  • MongoDB via Dotnet Core数据映射详解

    用好数据映射,MongoDB via Dotnet Core开发变会成一件超级快乐的事. 一.前言 MongoDB这几年已经成为NoSQL的头部数据库. 由于MongoDB free schema的特 ...

  • Java封装的概念详解

    一:封装的概念 Java是一门面向对象的语言,面向对象就是一种以组件化模式进行代码开发的思想,面向对象的理解你需要学完整个课程才会有感觉,面向对象有 三个基本特征:封装.继承.多态. 今天学习的是封装 ...

  • 从零开始学Java(九)详解Java中的方法

    方法 1.什么是方法,有什么用? (可以先看一下一个程序如果没有方法,会出现什么问题?) 方法(英语单词:method)是可以完成某个特定功能的并且可以被重复利用的代码片段. 方法的出现,让代码具有了 ...

  • Java类和对象 详解(一)

    一.面向对象简述 面向对象是一种现在最为流行的程序设计方法,几乎现在的所有应用都以面向对象为主了,最早的面向对象的概念实际上是由IBM提出的,在70年代的Smaltalk语言之中进行了应用,后来根据面 ...

  • (转)iOS使用Charles(青花瓷)抓包并篡改返回数据图文详解

    点击查看原文. 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教程,于是待问题解决后抽时间截了图,自己写一遍封存在博客园中以便以后随时查阅. charles又名 ...

  • R语言中使用read.table函数读取文件数据方法详解

    在R中,可以使用read.table()函数从具有多列表格形式的文件中读取数据.使用好它可以简单的从文本文件或CSV这种文件中读取数据. read.table()函数语法格式 read.table() ...