0

0

JVM 内存结构基于JDK1.8【JVM篇三】

雪夜

雪夜

发布时间:2025-07-20 11:26:01

|

445人浏览过

|

来源于php中文网

原创

大家好,我们又见面了,我是你们的朋友全栈君。

在上一篇文章《别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】》中,相信大家已经对Java类加载机制有了全面的了解。那么,类加载之后,字节码数据在Java虚拟机内存中是如何存放的?Java虚拟机在为类实例或成员变量分配内存时是如何分配的?这两个问题涉及到了JVM内存结构的知识,这篇文章将为大家解答。

文章目录: 1、内存结构还是运行时数据区? 2、运行时数据区 3、线程共享:Java堆、方法区 3.1、Java堆 3.2、JVM堆内存溢出后,其他线程是否可继续工作? 3.3、方法区 3.4、JDK1.8之前的方法区 3.5、JDK1.8之后的方法区 3.6、JDK1.8之后的方法区为何变化如此之大? 4、线程私有:程序计数器、Java虚拟机栈、本地方法栈 4.1、Java虚拟机栈(JVM Stacks) 4.2、本地方法栈(Native Method Stacks) 4.3、程序计数器 5、JVM内存结构总结

1、内存结构还是运行时数据区? 要解答本文提到的这些问题,我们首先需要了解一下Java虚拟机的内存结构。

2、运行时数据区 JVM被分为三个主要的子系统:类加载器子系统、运行时数据区和执行引擎。本文主要讲解其中的运行时数据区(Runtime Data Areas)。

JVM 内存结构基于JDK1.8【JVM篇三】 在Java虚拟机规范中,定义了五种运行时数据区,分别是Java堆、方法区、虚拟机栈、本地方法区、程序计数器。

顺便提一下,运行时常量池也会进入方法区,也就是说方法区中已经包括了常量池。

JVM 内存结构基于JDK1.8【JVM篇三】

3、线程共享:Java堆、方法区 我们首先来了解一下线程共享的Java堆和方法区。

3.1、Java堆 Java堆是内存空间中占用的最大一块区域,用于存放对象实例及数组,也就是说我们代码中通过new关键字创建的对象都存放在这里。因此,这里也是垃圾回收器的主要活动场所,被称为GC堆。每个JVM进程只有一个Java堆。根据垃圾回收器的规则,我们可以对Java堆进行进一步的划分,具体Java堆内存结构如下图所示:

JVM 内存结构基于JDK1.8【JVM篇三】 从上图可以看出,Java堆并不是单纯的一整块区域,实际上Java堆根据对象存活时间的不同,被分为年轻代和老年代两个区域。年轻代还被进一步划分为Eden区、From Survivor 0区和To Survivor 1区。默认的虚拟机配置比例是Eden:From:To = 8:1:1。

仔细看过上面的Java堆结构图的朋友可能会发现-Xms和-Xmn的字样,这正是控制堆的JVM参数。我们可以通过JVM参数动态控制Java堆中的各空间大小。JVM的参数有很多,但常用的就那么几个,用多了很容易记住。下面我们来讲讲关于堆的常见JVM参数:

当Java堆内没有足够的空间去完成实例分配,并且堆也无法扩展时,将会抛出常见的OutOfMemoryError异常,也就是我们常说的OOM异常。

3.2、JVM堆内存溢出后,其他线程是否可继续工作? JVM堆内存溢出后,也就是OOM异常,网上有一道非常火的面试题:JVM堆内存溢出后,其他线程是否可继续工作?

实际上这个问题需要具体场景分析。但是一般情况下,发生OOM的线程都会终止(除非代码写的太烂),该线程持有的对象占用的heap都会被GC回收,释放内存。因为发生OOM之前要进行GC,即便其他线程能够正常工作,也会因为频繁的GC产生较大的影响。

也就是说,发生OOM的线程一般情况下会死亡,也就是会被终止,该线程持有的对象占用的heap都会被GC回收,释放内存。因为发生OOM之前要进行GC,即便其他线程能够正常工作,也会因为频繁的GC产生较大的影响。

3.3、方法区 方法区(Method Area)与上面讲的Java堆一样,都是各个线程共享的,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但它有一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来。

3.4、JDK1.8之前的方法区 就以HotSpot虚拟机来说,在JDK1.8之前,方法区也被称作为永久代。这个方法区会发生我们常见的java.lang.OutOfMemoryError: PermGen space异常,注意是永久代异常信息,我们也可以通过启动参数来控制方法区的大小。

在JDK7之前的HotSpot虚拟机中,纳入字符串常量池的字符串被存储在永久代中,因此导致了一系列的性能问题和内存溢出错误。特别突出的例子就是String的intern()方法。

3.5、JDK1.8之后的方法区 JDK8之后就没有永久代这一说法,取而代之的是元空间(meta space),而且将老年代与元空间剥离。元空间放置于本地的内存中,因此元空间的最大空间就是系统的内存空间,从而不会再出现像永久代的内存溢出错误,也不会出现泄漏的数据移到交换区这样的事情。用户可以为元空间设置一个可用空间最大值,不设置的话默认根据类的元数据大小动态增加元空间的容量。对于一个64位的服务器端JVM来说,其默认的-XX:MetaspaceSize值为21MB。也就是说,默认的元空间大小是21MB。

只要类加载器还存活,其加载的类的元数据也是存活的,不会被回收掉,也就是同生共死。

JVM 内存结构基于JDK1.8【JVM篇三】

3.6、JDK1.8之后的方法区为何变化如此之大? 做这个改变主要是基于以下两点原因:

1、由于永久代(PermGen)内存经常会溢出,引发恼人的java.lang.OutOfMemoryError: PermGen,因此JVM的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的OOM错误。

CWC 大型商城
CWC 大型商城

基于jsp+javabean+mysql三层结构的动态购物网站,网站用户接口(即界面)由jsp完成,数据和逻辑处理由beans完成,数据储存由mysql完成 主要做了以下一些修正: 1.新增产品站内搜索引擎。 2.新增人气商品排行。 3.新增热评商品排行。 4.新增重点推荐产品。 5.删除不太需要的新闻频道。 6.修正后台管理的一些Nullpointexception错误。 7.新增顾客资料修改。

下载

2、移除永久代(PermGen)可以促进HotSpot JVM与JRockit VM的融合,因为JRockit没有永久代。

4、线程私有:程序计数器、Java虚拟机栈、本地方法栈 Java堆以及方法区的数据是共享的,但是有一些部分是线程私有的。线程私有部分可以分为:程序计数器、Java虚拟机栈、本地方法栈三大部分。

4.1、Java虚拟机栈(JVM Stacks) 1、Java虚拟机的每一条线程都有自己私有的Java虚拟机栈,这个Java虚拟机栈与线程同时创建,因此它与线程有相同的生命周期。

2、Java虚拟机栈描述的是Java方法执行的内存模型:每一个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在Java虚拟机栈中的入栈到出栈的过程。

3、局部变量表存放了编译期可知的各种基本数据类型、对象引用和returnAddress类型。其中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

4、Java虚拟机栈既允许被实现成固定的大小,也允许根据计算动态扩展和收缩。如果采用固定大小的话,每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。在Java虚拟机栈中会发生两种异常,这个在虚拟机规范中有指出:

如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出StackOverflowError异常;也就是栈溢出错误!方法递归调用产生StackOverflowError异常这种结果。如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存或者在创建新的线程时没有足够的内存去创建对应的Java虚拟机栈,那么虚拟机将会抛出OutOfMemoryError异常。也就是OOM内存溢出错误!(线程启动过多)当然,可以通过参数-Xss去调整JVM栈的大小。

4.2、本地方法栈(Native Method Stacks) 和虚拟栈相似,只不过它服务于Native方法,线程私有。当Java虚拟机使用其他语言(例如C语言)来实现指令集解释器时,也会使用到本地方法栈。如果Java虚拟机不支持native方法,并且自己也不依赖传统栈的话,可以无需支持本地方法栈。

与Java虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

HotSpot虚拟机直接就把本地方法栈和虚拟机栈合二为一。

4.3、程序计数器 当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。

5、JVM内存结构总结 JVM 内存结构基于JDK1.8【JVM篇三】 程序计数器:

Java虚拟栈:

Native方法栈:

Java堆:

方法区:

发布者:全栈程序员栈长,转载请注明出处:https://www.php.cn/link/c0243062e292cce3284a1cd9a8e30300 原文链接:https://www.php.cn/link/c8377ad2a50fb65de28b11cfc628d75c

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

410

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

637

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

362

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

263

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

629

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

562

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

669

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

618

2023.09.22

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Rust 教程
Rust 教程

共28课时 | 6.8万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

Go 教程
Go 教程

共32课时 | 6.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号