Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >(2)JVM——Java 虚拟机运行时数据区域讲解

(2)JVM——Java 虚拟机运行时数据区域讲解

作者头像
凡人飞
发布于 2020-09-20 12:17:26
发布于 2020-09-20 12:17:26
4350
举报
文章被收录于专栏:指缝阳光指缝阳光

一、简述

  1. 介绍:如果有了解 C/C++,以及 Java 语言的朋友,肯定知道它们之间最大的差别的就是对于内存的回收。用 C/C++ 时,自己创建的对象得自己回收内存,而 Java 则是因为其自带的垃圾收集器,将开发者解放出来。犹记得当初大学学 C 语言,讲到指针的那一节,就感觉指针是无所不能,各种灵活,不过如果用不好就容易飘。本篇博客主要简单介绍一下 Java 虚拟对于内存的划分,以及大概作用。

二、内存运行时数据区

  1. 这张图片展示的就是 JVM 对于内存的经典划分,主要分为了程序计数器虚拟机本地方法栈方法区,同时还有运行时常量池直接内存
  2. 程序计数器
    • 线程私有(每条线程独立有一个),可以看成当前线程所执行的字节码的行号指示器。
    • 如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地方法,这个计数器值则应为空。
    • 此内存区域是唯一没有 OutOfMemoryError 情况的区域
  3. 虚拟机栈: 通俗的讲,一个线程有一个虚拟机栈,这个栈就是一个中间容器,帮助线程在执行过程中完成各项处理。其中栈里面的一个基础单位就是栈帧,一个栈帧可以简单的对应一个方法,在进入方法后会有局部变量等数据,此时就创建一个栈帧来保存这些信息(比如局部变量表、操作数栈、动态连接、方法出口等信息)。栈是先进后出的数据结构。虚拟机栈特点如下:
    • 线程私有,生命周期与线程相同
    • 一个方法的执行对应一个栈帧的入栈和出栈过程
    • 局部变量表存放 8 种基本数据类型、对象引用和 returnAddress 类型
    • long 和 double 占用两个变量槽,其他类型是只占一个
    • 两类异常状况: ① 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverFlowError 异常 ② 如果 Java 虚拟机栈容量可以动态扩展(HotSpot 不可以),当栈扩展时无法申请到足够的内存会抛出 OutOfMemoryError 异常
  4. 本地方法栈:本地方法栈和虚拟机栈基本一样,区别是 虚拟机栈为虚拟机执行 Java 方法(字节码)服务,而本地方法栈是为虚拟机使用到的本地方法服务 。异常和虚拟机栈的一致。本地方法解释可以查看——详解native方法的使用
  5. Java 堆:堆是虚拟机管理的内存中最大的一块,这块地方存放了 Java 中几乎所有的对象实例(有容乃大)。因为这块地方大,并且发生的故事多,所以内存的回收(垃圾收集器)都发生在这儿,因此也被叫为 “GC堆”。有四处特点如下:
    • 虽然堆是线程共享的,但是在共享的地方也会为线程划分私有的分配缓冲区
    • Java 堆在内存物理上可能不连续,但是对于我们使用来说,逻辑上是连续的
    • 虚拟机实现堆是可扩展的,通过参数 -Xmx 和 -Xms 设置
    • 在堆中没有内存可以进行实例分配时,也无法扩展,则会抛出 OutOfMemoryError 异常
  6. 方法区:与 Java堆 一样是线程共享的,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。注意:经常会将“永久代”和方法区混淆,他们的区别是 方法区是 JVM 的一种规范,而永久代是对这一种规范的实现。查看:方法区和永久代区别。特点如下:
    • 在 jdk7 中已经将字符串常量池从方法区移除,并在Java堆中开辟一块新的区域存放字符串常量池
    • 在 jdk8 中将永久代去除了,使用元空间来实现,元空间的内存区域使用本地内存
    • 如果方法区无法满足新的内存分配需求时,将抛出 OutOfMemoryError 异常
  7. 运行时常量池:运行时常量池是方法区的一部分,存放编译器生成的各种字面量和符号引用。特点如下:
    • 具备动态性,常量池的数据不是都在编译器存入的,还可以在运行时添加,比如 String 的 intern() 方法
    • 常量池无法申请到内存时抛出 OutOfMemoryError 异常
    • 对于各个版本方法区的区别如表格 1-1
  8. 直接内存:直接内存不是虚拟机运行时数据的一部分,其分配不会受到 Java 堆大小的限制。
    • 在 JDK1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,在一些场景能显著提高性能
    • 也可能出现 OutOfMemoryError 异常

表格 1-1

jdk1.7以前

jdk1.7

jdk1.8

字符串常量池在方法区中,实现为永久代

字符串常量池在堆中,实现为永久代

字符串常量池在堆中,实现为元空间

深入理解Java虚拟机第三版》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JVM深入原理(七)(二):运行时数据区
java.lang.OutOfMemoryError: Java heap space
摘星.
2025/05/20
760
JVM深入原理(七)(二):运行时数据区
JVM运行时数据区域及GC
方法区 (Method Area or Permanent Generation):
哲洛不闹
2018/09/14
3880
JVM初探(一):jvm内存结构[通俗易懂]
我们知道java代码先编译为.class文件,然后再将.class文件交由jvm执行。在程序运行的这一过程中,jvm会将其管理的内存空间划分为不同的区域,这些区域各有各的用途,我们将其分为五类:
全栈程序员站长
2022/09/23
3940
JVM初探(一):jvm内存结构[通俗易懂]
一问带你彻底了解JVM-Java内存区域详解
Java内存模型在1.8之前和1.8之后略有不同,也就是运行时数据区域,请看如下图:
@派大星
2023/06/28
4850
一问带你彻底了解JVM-Java内存区域详解
JVM 系列(1) —— 运行时数据区域
Java 虚拟机会在 Java 运行程序的过程中把它所管理的内存分为若干个不同的数据区域
求和小熊猫
2020/12/16
2900
JVM 系列(1) —— 运行时数据区域
JVM--运行时数据区
Java虚拟机在执行Java程序时,会把它所管理的内存划分为若干个数据区域,这些区域各有各的用途。
SuperHeroes
2019/03/12
4460
JVM 运行时数据区域,书中没有说清楚的方法区、永久代、元空间
数据库系列吭哧吭哧写得差不多了,准备寒假看完 JVM,然后开学来看看框架背背八股就准备秋招了。话不多说,JVM 第一个知识点必定要奉献给 Java 程序运行时的数据区域划分。
飞天小牛肉
2022/02/23
7520
JVM 运行时数据区域,书中没有说清楚的方法区、永久代、元空间
【107期】谈谈面试必问的Java内存区域(运行时数据区域)和内存模型(JMM)
来自:www.cnblogs.com/czwbig/p/11127124.html
良月柒
2021/01/07
6580
【107期】谈谈面试必问的Java内存区域(运行时数据区域)和内存模型(JMM)
Java运行时数据区域
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。其包括:程序计数器、Java虚拟机栈、本地方法栈、Java堆和方法区。
conanma
2021/12/06
3480
JVM运行时数据区(<=JDK7 and JDK8+)
是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。
斯武丶风晴
2020/04/24
7640
JVM运行时数据区(<=JDK7  and  JDK8+)
JAVA运行时数据区域
根据《Java 虚拟机规范(Java SE 7版)》规定,Java虚拟机所管理的内存将会包括一下几个运行时数据区域:
爱撸猫的杰
2019/03/28
5410
JAVA运行时数据区域
JVM笔记【1】-- 运行时数据区
C/C++每一个new操作都需要自己去delete/free,而java里面有虚拟机自动管理内存,不容易出现内存泄漏或者溢出的问题,但是不容易出现不代表不出现,了解虚拟机怎么使用和管理内存是十分重要的是,对程序优化或者问题排查有帮助。
秦怀杂货店
2020/12/26
2470
JVM | 运行时数据区的JVM规范
在这一块的学习时, 我们容易陷入一个误区,就是一上来就直接搜索运行时数据区, 网上有些文章对虚拟机规范和HOTSPOT实现没有区分开,导致有时候大家看的两篇文章解释尽不一样. 自己也容易糊涂. 所以本篇特地将两个拆开讲. 且尽量以官方文档为准
微笑的小小刀
2020/02/17
7800
JVM - 运行时数据区
Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中的类加载器加载各个类的字节码文件,加载完毕之后,交由JVM执行引擎执行。
用户2987604
2020/06/15
3620
JVM - 运行时数据区
Java的运行时数据区域
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有些区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。
真正的飞鱼
2023/04/02
5040
Java的运行时数据区域
探究JVM——运行时数据区
最近在读《深入理解Java虚拟机》,收获颇丰,记录一下,部分内容摘自原书。 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁
欠扁的小篮子
2018/04/11
6580
探究JVM——运行时数据区
《深入理解Java虚拟机》(二)java虚拟机运行时数据区
Java虚拟机运行时数据区 详解 2.1 概述 本文参考的是周志明的 《深入理解Java虚拟机》,为了整理思路,简单记录一下,方便后期查阅。 2.2 运行时数据区域 Java虚拟机在Java程序运行时
程序员鹏磊
2018/02/09
9920
《深入理解Java虚拟机》(二)java虚拟机运行时数据区
JDK8之后-JVM运行时数据区域
首先弄清几个概念: 1.方法区(method area)只是JVM规范中定义的一个概念,用于存储类信息、常量池、静态变量、JIT编译后的代码等数据,具体放在哪里,不同的实现可以放在不同的地方。永久代是HotSpot虚拟机特有的概念,是对方法区的实现,别的JVM没有永久代的概念。(虽然去除了永久代,但是方法区作为概念上的区域仍然存在) 2.在JDK8中,JDK8的HotSpot VM已经是以前的HotSpot VM与JRockit VM的合并版,也就是传说中的“HotRockit”,只是产品里名字还是叫HotSpot VM。所以对于说JDK8去除永久代换成元空间的说法,就是默指的合并后的HotSpot虚拟机。 3.为什么要将永久代去除呢? 一方面是节省空间,避免了常见的永久内存错误:java.lang.OutOfMemoryError: PermGen问题。另一方面是为了整合JRockit,因为JRockit没有永代区这样类似的空间。 其实,从jdk7开始,就开始了永久代的转移工作,将譬如符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;等。但是指导JDK8永久代才被元空间替代。 4.元空间又是什么呢?以前存储在永久代里面的数据现在存在了哪里? 元空间是一块与堆不相连的本地内存。原本存在永久代的数据,一部分移到了java堆里面,一部分移到了本地内存里面(即元空间)(文档中原句:Move part of the contents of the permanent generation in Hotspot to the Java heap and the remainder to native memory.) 。永久代中原来存储的字符串常量(池)、符号引用(这两个在jdk7普遍就已经将其放在堆上了)和类的静态变量现在存储在java堆中,其余的数据作为元数据存储在元空间中。 5.什么是元数据呢? 元数据是数据的数据或者叫做用来描述数据的数据或者叫做信息的信息。(比如原本方法区存储的类信息、即时编译器编译后的代码等),也可以把元数据简单的理解成,最小的数据单位。元数据可以为数据说明其元素或属性(名称、大小、数据类型、等),或其结构(长度、字段、数据列),或其相关数据(位于何处、如何联系、拥有者)。 6.元空间详细:http://blog.csdn.net/lk7688535/article/details/51767460
洋仔聊编程
2019/01/15
1.6K0
JVM运行时数据区知多少
java引以为豪的就是内存自动化管理,不需要像C、C++等一样需要开发者手动获取内存、释放内存,对内存进行操作等,java在这方面做的非常好、非常方便。所以,了解java内存区域是怎么划分的是非常有必要的,面试的时候也是经常会问到的。
索码理
2022/12/28
3620
JVM运行时数据区知多少
JDK1.8-Java虚拟机运行时数据区域和HotSpot虚拟机的内存模型
官方文档中规定的运行时数据区一共就几块: PC计数器, 虚拟机栈, 本地方法栈, 堆区, 方法区, 运行时常量池. 这里的官方规定是说, 如果你要做一个Java虚拟机的话, 必须要包含这几个区域, 但是这几个区域在你的虚拟机中是用哪块内存实现的, 这由虚拟机制作者决定.
java架构师
2019/04/25
6210
JDK1.8-Java虚拟机运行时数据区域和HotSpot虚拟机的内存模型
相关推荐
JVM深入原理(七)(二):运行时数据区
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档