bitpie官网下载苹果版|元空间
面试官 | JVM 为什么使用元空间替换了永久代? - 知乎
面试官 | JVM 为什么使用元空间替换了永久代? - 知乎切换模式写文章登录/注册面试官 | JVM 为什么使用元空间替换了永久代?码上技术指导老师码上Teacher-Q指导226985935在Java8和以后版本中JVM的内存结构慢慢发生了变化。作为面试官如果你还不知道,那么面试过程中是不是有些露怯?作为面试者,如果知晓这些变化,又将成为面试中的亮点。如果在网络上搜索JVM内存结构,90%的可能会搜到Java7及以前的内存图,本篇文章将会对JVM内存结构再次细化,深入理解Java8之后内部的变化。现在意识到关注公众号“程序新视界”的好处了吧。在这里可以不断的刷新你的知识和认知。JVM内存结构的细化再来看一下JVM内存结构图。为了更细化的讲解,我们将该图进行进一步的优化调整。针对java7及以前版本的细化。看出变化了吗?堆和方法区连在了一起,但这并不能说堆和方法区是一起的,它们在逻辑上依旧是分开的。但在物理上来说,它们又是连续的一块内存。也就是说,方法区和前面讲到的Eden和老年代是连续的。在继续进行下去之前,我们先来理解两个概念:规范和实现。规范和实现针对Java虚拟机的实现有专门的《Java虚拟机规范》,在遵守规范的前提下,不同的厂商会对虚拟机进行不同的实现。 就好比开发的过程中定义了接口,具体的接口实现大家可以根据不同的业务需求进行实现。PS:大家都有必要了解一下《Java虚拟机规范》,关注公众号“程序新视界”,回复“002”获得Java SE 7的虚拟机规范PDF版。我们通常使用的Java SE都是由Sun JDK和OpenJDK所提供,这也是应用最广泛的版本。而该版本使用的VM就是HotSpot VM。通常情况下,我们所讲的java虚拟机指的就是HotSpot的版本。永久代(PermGen)上面理解了规范和实现之后,来看认识一个概念“永久代(Permanet Generation,也称PermGen)”。对于习惯了在HotSpot虚拟机上开发、部署的程序员来说,很多都愿意将方法区称作永久代。本质上来讲两者并不等价,仅因为Hotspot将GC分代扩展至方法区,或者说使用永久代来实现方法区。在其他虚拟机上是没有永久代的概念的。也就是说方法区是规范,永久代是Hotspot针对该规范进行的实现。理解上面的概念之后,我们对Java7及以前版本的堆和方法区的构造再进行一下变动。再重复一遍就是对Java7及以前版本的Hotspot中方法区位于永久代中。同时,永久代和堆是相互隔离的,但它们使用的物理内存是连续的。永久代的垃圾收集是和老年代捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。但在Java7中永久代中存储的部分数据已经开始转移到Java Heap或Native Memory中了。比如,符号引用(Symbols)转移到了Native Memory;字符串常量池(interned strings)转移到了Java Heap;类的静态变量(class statics)转移到了Java Heap。然后,在Java8中,时代变了,Hotspot取消了永久代。永久代真的成了永久的记忆。永久代的参数-XX:PermSize和-XX:MaxPermSize也随之失效。元空间(Metaspace)对于Java8,HotSpots取消了永久代,那么是不是就没有方法区了呢?当然不是,方法区只是一个规范,只不过它的实现变了。在Java8中,元空间(Metaspace)登上舞台,方法区存在于元空间(Metaspace)。同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。当Java Heap空间不足时会触发GC,但Native memory空间不够却不会触发GC。针对Java8的调整,我们再次对内存结构图进行调整。元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“java.lang.OutOfMemoryError: PermGen space”这种错误。看上图中的方法区,是不是“膨胀”了。默认情况下元空间是可以无限使用本地内存的,但为了不让它如此膨胀,JVM同样提供了参数来限制它使用的使用。-XX:MetaspaceSize,class metadata的初始空间配额,以bytes为单位,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当的降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize(如果设置了的话),适当的提高该值。-XX:MaxMetaspaceSize,可以为class metadata分配的最大空间。默认是没有限制的。-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为class metadata分配空间导致的垃圾收集。-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为class metadata释放空间导致的垃圾收集。永久代为什么被替换了思考一下,为什么使用元空间替换永久代?表面上看是为了避免OOM异常。因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。更深层的原因还是要合并HotSpot和JRockit的代码,JRockit从来没有所谓的永久代,也不需要开发运维人员设置永久代的大小,但是运行良好。同时也不用担心运行性能问题了,在覆盖到的测试中, 程序启动和运行速度降低不超过1%,但是这点性能损失换来了更大的安全保障。原文链接 Java学习路线 码上发布于 2020-03-08 22:55面试官Java 虚拟机(JVM)HotSpot VM赞同 10010 条评论分享喜欢收藏申请
JVM 运行时内存空间详解——元空间_jvm 元空间-CSDN博客
>JVM 运行时内存空间详解——元空间_jvm 元空间-CSDN博客
JVM 运行时内存空间详解——元空间
最新推荐文章于 2024-03-04 22:02:55 发布
格子衫111
最新推荐文章于 2024-03-04 22:02:55 发布
阅读量1.3w
收藏
71
点赞数
16
分类专栏:
JVM
文章标签:
oracle
c#
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012660464/article/details/119900702
版权
JVM
专栏收录该内容
8 篇文章
9 订阅
订阅专栏
通过上一篇文章,我们大体了解了JVM的整体架构,其分为:元数据(JDK7是方法区)、堆、虚拟机栈、本地方法栈、程序计数器几个部分。 本篇文章,咱们对元空间进行剖析,一探究竟。
1. 元空间介绍
在JDK1.7之前,HotSpot 虚拟机把方法区当成永久代(方法区的落地实现)来进行垃圾回收。而从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。HotSpots取消了永久代,那么是不是也就没有方法区了呢?当然不是,方法区是一个规范,规范没变,它就一直在,只不过取代永久代的是元空间(Metaspace)而已。
它和永久代有什么不同的? 存储位置不同:永久代在物理上是堆的一部分,和新生代、老年代的地址是连续的,而元空间属于本地内存。 存储内容不同:在原来的永久代划分中,永久代用来存放类的元数据信息、静态变量以及常量池等。现在类的元信息存储在元空间中,静态变量和常量池等并入堆中,相当于原来的永久代中的数据,被元空间和堆内存给瓜分了。
2. 为什么要废弃永久代,引入元空间?
相比于之前的永久代划分,Oracle为什么要做这样的改进呢?
在原来的永久代划分中,永久代需要存放类的元数据、静态变量和常量等。它的大小不容易确定,因为这其中有很多影响因素,比如类的总数,常量池的大小和方法数量等,-XX:MaxPermSize 指定太小很容易造成永久代内存溢出。移除永久代是为融合HotSpot VM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。永久代会为GC带来不必要的复杂度,并且回收效率偏低。
3. 废除永久代的好处
由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间。不会遇到永久代存在时的内存溢出错误。将运行时常量池从PermGen分离出来,与类的元数据分开,提升类元数据的独立性。将元数据从PermGen剥离出来到Metaspace,可以提升对元数据的管理同时提升GC效率。
4. Metaspace相关参数
-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。如果没有使用该参数来设置类的元数据的大小,其最大可利用空间是整个系统内存的可用空间。 JVM也可以增加本地内存空间来满足类元数据信息的存储。但是如果没有设置最大值,则可能存在bug导致Metaspace的空间在不停的扩展,会导致机器的内存不足;进而可能出现swap内存被耗尽;最终导致进程直接被系统直接kill掉。如果设置了该参数,当Metaspace剩余空间不足,会抛出java.lang.OutOfMemoryError: Metaspace space-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集。-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集。
优惠劵
格子衫111
关注
关注
16
点赞
踩
71
收藏
觉得还不错?
一键收藏
知道了
2
评论
JVM 运行时内存空间详解——元空间
通过上一篇文章,我们大体了解了JVM的整体架构,其分为:元数据(JDK7是方法区)、堆、虚拟机栈、本地方法栈、程序计数器几个部分。本篇文章,咱们对元空间进行剖析,一探究竟。1. 元空间介绍在JDK1.7之前,HotSpot 虚拟机把方法区当成永久代来进行垃圾回收。而从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。HotSpots取消了永久代,那么是不是也就没有方法区了呢?当然不是,方法区是一个规范,规范没变,它就一直在,只不过取代永久代的是元空
复制链接
扫一扫
专栏目录
jav程序监控并记录jvm运行时内存、线程、垃圾收集和堆空间
03-25
1. jav程序监控并记录jvm运行时内存、线程、垃圾收集和堆空间
2. 定时记录到本地文件中;
3. 可以设置记录的时间间隔和循环记录次数;
4. 在监控不完善的情况下,可以记录java进程异常退出之前的jvm状态信息;
5. java源码实现,不依赖第三方组件;
JVM内存空间分配笔记
10-24
主要是JVM内存分配及简单的JVM性能调优
2 条评论
您还未登录,请先
登录
后发表或查看评论
JVM学习笔记---JVM运行时内存之元空间
qq_39314972的博客
07-11
1388
JVM学习笔记—JVM运行时内存之元空间
1. 元空间简介
在JDK1.7之前,HotSpot 虚拟机把方法区当成永久代来进行垃圾回收。
而从 JDK 1.8 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。
HotSpots取消了永久代,那么是不是也就没有方法区了呢?
当然不是,方法区是一个规范,规范没变,它就一直在,只不过取代永久代的是元空间(Metaspace)而已。它和永久代有什么不同的?
2. 永久代和元空间的区别
存储位置不同:永久代在物理上是堆的一部分,和新生
JVM——元空间(Metaspace)
qq_36996635的博客
06-29
478
一、从方法区(PermGen)到元空间(Metaspace)
方法区(PermGen)
JDK1.8以前的HotSpot JVM有方法区,也叫永久代(permanent generation)。
方法区用于存放已被虚拟机加载的类信息、常量、静态变量,即编译器编译后的代码。
方法区是一片连续的堆空间,通过-XX:MaxPermSize来设定永久代最大可分配空间,当JVM加载的类信息容量超过了这个值,会报OOM:PermGen错误。
永久代的GC是和老年代(old generation)捆绑在一起的,无
JVM 元空间、java中的元空间
LIJINGPO的博客
01-12
1154
上述运行结果可以看出,相同的代码,在JDK 1.6会出现“PermGen Space”的永久代内存溢出,而在JDK 1.7和JDK 1.8中,会出现"Java heap space"堆内存溢出,并且DK 1.8中 PermSize和MaxPermGen参数已经无效。因此,在JDK 1.7和JDK 1.8中,已经将字符串常量由永久代转移到堆中,并且JDK 1.8中已经完全移除了永久代,采用元空间来代替。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过运行参数来指定元空间的大小。
JVM运行时数据区原理解析
08-25
主要介绍了JVM运行时数据区原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
JVM方法区(元空间)
抽象的螺旋
11-17
6983
概述
运行时数据区概览
从线程共享的角度看方法区、堆、栈、程序计数器
方法区、堆、栈之间的关系
栈中的reference就是person变量,堆中的到对象类型数据的指针指向方法区的对象类型数据就是Person。
...
全网最硬核 JVM 内存解析 - 8.元空间的核心概念与设计
hashcon
04-26
388
网上有很多关于 JVM 内存结构的分析以及图片,但是由于不是一手的资料亦或是人云亦云导致有很错误,造成了很多误解;并且,这里可能最容易混淆的是一边是 JVM Specification 的定义,一边是 Hotspot JVM 的实际实现,有时候人们一些部分说的是 JVM Specification,一部分说的是 Hotspot 实现,给人一种割裂感与误解。本篇主要从 Hotspot 实现出发,以 Linux x86 环境为主,紧密贴合 JVM 源码并且辅以各种 JVM 工具验证帮助大家理解 JVM 内存的结
JVM--方法区&元空间
m0_69057918的博客
06-09
3360
JVM--方法区&元空间详解
JVM10:元空间(Meta Space,方法区)
Hicodden的博客
04-22
5742
文章目录元空间(Meta Space)1、元空间的基本介绍2、Meta Space的演进永久代为什么要被元空间替换3、设置方法区大小和OOMJDK 8及以后4、元空间( Meta Space)存储什么?类型信息域(Field)信息方法(Method)信息静态变量(non-fianal的类变量)运行时常量池(Runtime Constant Pool)5、运行时常量池VS常量池
元空间(Meta Space)
1、元空间的基本介绍
在Java 8 中称为元空间(Meta Space),在Java 7 及以前称
【JVM】JVM内存结构之——方法区(元空间)
记录各种Bug解决案例及日常学习内容
05-12
2677
目录1. 栈、堆、方法区的交互关系2. 方法区的理解3. 设置方法区大小与 OOM3.1 JDK7及以前(永久代)3.2 JDK8及以后(元空间)4. 方法区OOM异常如何解决4.1 JDK7及以前(永久代)4.2 JDK8及以后(元空间)5. 方法区的内部结构5.1 类型信息5.2 域(Field)信息5.3 方法(Method)信息6. 永久代演进过程6.1 永久代为什么要被元空间替代?6.2 字符串常量池为什么要调整位置?6.3 如何证明 静态变量是存放在堆中?
⽅法区与 Java 堆⼀样,是各个线
详解JVM中的本机内存跟踪
08-25
在本文里小编给大家整理了一篇关于JVM中的本机内存跟踪的相关知识点内容,有兴趣的朋友们参考学习下。
详解JVM 运行时内存使用情况监控
08-26
主要介绍了详解JVM 运行时内存使用情况监控,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Java内存模型与JVM运行时数据区的区别详解
08-25
主要介绍了Java内存模型与JVM运行时数据区的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
详解Java虚拟机(JVM)运行时
08-26
JVM(Java虚拟机)是一个抽象的计算模型。这篇文章主要介绍了Java虚拟机(JVM)运行时的相关知识,需要的朋友可以参考下
JVM原理之运行时数据区详解
12-22
4. 运行时数据区 关于运行时数据官方解释:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5 4.1 堆 (heap) 堆在虚拟机中是一块共享区域, 存放 对象实例 和数组; 堆在虚拟机启动的时候...
JVM运行时数据区划分原理详解
08-19
主要介绍了JVM运行时数据区划分原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
1.4 数据库系统的组成
最新发布
2403_83073833的博客
03-04
422
1. 决定数据库中的信息内容和结构 2. 决定数据库的存储结构和存取策略 3. 定义数据的安全性要求和完整性约束条件 4.监控数据库的使用和运行(周期性转储数据库(数据文件/日志文件),系统故障恢复,介质故障恢复,监视审计文件)5. 数据库的改进和重组(性能监控和调优,定期对数据库进行重组织,以提高系统的性能;数据库系统的软件主要有:数据库管理系统,支持数据库管理系统运行的操作系统,与数据库接口的高级语言及其编译系统,以数据库管理系统为核心的应用开发工具,为特定应用环境开发的数据库应用系统。
MySQL进阶:全局锁、表级锁、行级锁总结
m0_52380556的博客
03-02
1021
MySQL进阶:全局锁、表级锁、行级锁总结
jvm运行时内存区域
10-17
JVM运行时内存区域主要包括程序计数器、虚拟机栈、本地方法栈、Java堆、方法区(包括运行时常量池)和直接内存。其中,直接内存虽然不是虚拟机规范中定义的内存区域,但也会被频繁地使用,并且可能导致OutOfMemoryError错误出现。
程序计数器用于记录当前线程执行的字节码的行号,虚拟机栈用于存储方法执行时的局部变量表、操作数栈、动态链接、方法出口等信息,本地方法栈则为虚拟机栈为本地方法服务。Java堆是JVM管理的最大的一块内存区域,用于存储对象实例和数组,方法区则用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
格子衫111
CSDN认证博客专家
CSDN认证企业博客
码龄10年
暂无认证
144
原创
2万+
周排名
1万+
总排名
231万+
访问
等级
6668
积分
436
粉丝
1588
获赞
459
评论
5274
收藏
私信
关注
热门文章
mysql中一条insert语句批量插入多条记录
357922
maven的下载与安装教程(超详细)
264637
MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
193078
group by分组后获得每组中时间最大的那条记录
148242
COUNT()函数详解
134173
分类专栏
工具使用
32篇
mybatis
4篇
Spring
1篇
算法与数据结构
6篇
面试题
6篇
JVM
8篇
杂谈
1篇
前端
5篇
Java SE
34篇
JavaWeb
27篇
Android知识点
19篇
开发环境配置
3篇
错误记录
16篇
Java 框架
21篇
TCP/IP协议和通讯原理
1篇
数据库
26篇
Linux
4篇
最新评论
Vue-cli(vue脚手架)超详细教程
醉挽清风141:
特别详细,感谢博主
手把手教你在IDEA中创建一个Maven+Spring MVC的入门项目
一人舛木:
tomcat 版本低一点 我tomcat10 不行 换成tomcat8就行了
手把手教你在IDEA中创建一个Maven+Spring MVC的入门项目
一人舛木:
wys
MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
阿昱向前冲:
我的MAC系统用这个:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
maven的下载与安装教程(超详细)
2301_78123544:
大好人
最新文章
重写Java的equals方法,一般用于对象判重
VLOOKUP函数的使用方法
如何导出数据库数据字典
2024年1篇
2023年29篇
2022年44篇
2021年44篇
2020年12篇
2018年2篇
2017年10篇
2016年33篇
目录
目录
分类专栏
工具使用
32篇
mybatis
4篇
Spring
1篇
算法与数据结构
6篇
面试题
6篇
JVM
8篇
杂谈
1篇
前端
5篇
Java SE
34篇
JavaWeb
27篇
Android知识点
19篇
开发环境配置
3篇
错误记录
16篇
Java 框架
21篇
TCP/IP协议和通讯原理
1篇
数据库
26篇
Linux
4篇
目录
评论 2
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
添加红包
祝福语
请填写红包祝福语或标题
红包数量
个
红包个数最小为10个
红包总金额
元
红包金额最低5元
余额支付
当前余额3.43元
前往充值 >
需支付:10.00元
取消
确定
下一步
知道了
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝
规则
hope_wisdom 发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
0
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。
余额充值
jvm中的元空间和直接内存(堆外内存)的关系是什么?元空间=直接内存吗? - 知乎
jvm中的元空间和直接内存(堆外内存)的关系是什么?元空间=直接内存吗? - 知乎首页知乎知学堂发现等你来答切换模式登录/注册Java 虚拟机(JVM)内存(RAM)内存管理jvm中的元空间和直接内存(堆外内存)的关系是什么?元空间=直接内存吗?关注者14被浏览36,856关注问题写回答邀请回答好问题 5添加评论分享6 个回答默认排序大头菜Java 关注先给结论:包含关系。堆外内存包含元空间。用一个宏观图来感受一下:图片摘自网络你看图就可以明白,你可以简单理解为:物理内存=堆外内存+堆内内存。现在元空间不在堆内,自然就在堆外。下面是元空间的一些详细介绍:首先,什么是 MetaspaceMetaspace 区域位于堆外,所以它的最大内存大小取决于系统内存,而不是堆大小,我们可以指定 MaxMetaspaceSize 参数来限定它的最大内存。Metaspace 是用来存放 class metadata 的,class metadata 用于记录一个 Java 类在 JVM 中的信息,包括但不限于 JVM class file format 的运行时数据: 1、Klass 结构,这个非常重要,把它理解为一个 Java 类在虚拟机内部的表示吧;2、method metadata,包括方法的字节码、局部变量表、异常表、参数信息等;3、常量池,比如一些字符串之类的4、注解;5、方法计数器,记录方法被执行的次数,用来辅助 JIT 决策虽然每个 Java 类都关联了一个 java.lang.Class 的实例,而且它是一个贮存在堆中的 Java 对象。但是类的 class metadata 不是一个 Java 对象,它不在堆中,而是在 Metaspace 中。了解什么是元空间后,接着看一下元空间的分配和回收。什么时候分配 Metaspace 空间当一个类被加载时,它的类加载器会负责在 Metaspace 中分配空间用于存放这个类的元数据什么时候回收 Metaspace 空间分配给一个类的空间,是归属于这个类的类加载器的,只有当这个类加载器卸载的时候,这个空间才会被释放。所以,只有当这个类加载器加载的所有类都没有存活的对象,并且没有到达这些类和类加载器的引用时,相应的 Metaspace 空间才会被 GC(full gc) 释放。如何配置 Metaspace 空间-XX:MaxMetaspaceSize:Metaspace 总空间的最大允许使用内存,默认是不限制。-XX:CompressedClassSpaceSize:Metaspace 中的 Compressed Class Space 的最大允许内存,默认值是 1G,这部分会在 JVM 启动的时候向操作系统申请 1G 的虚拟地址映射,但不是真的就用了操作系统的 1G 内存。发布于 2021-04-23 14:27赞同 122 条评论分享收藏喜欢收起洛神灬殇互联网行业 资深工程师 关注元数据空间在内存区域角度而言被分配到了堆外的内存空间里面,与堆内存不在物理相连接,相对的之前的永久带虽然叫做非堆,但实际内存空间是与堆内存相连接的。所以从属关系 元数据空间从属于直接内存发布于 2021-05-03 13:37赞同 14 条评论分享收藏喜欢
一文搞懂JVM之 方法区、永久代、元空间三者的区别 - 知乎
一文搞懂JVM之 方法区、永久代、元空间三者的区别 - 知乎首发于java虚拟机切换模式写文章登录/注册一文搞懂JVM之 方法区、永久代、元空间三者的区别码小刀简要回答方法区实在虚拟机规范里面被定义的,不同的虚拟机对这个定义的实现不同,在HotSpot 虚拟机中在 jdk1.7 版本之前的方法区实现叫永久代(PermGen space),jdk1.8 之后叫做元空间(Metaspace)。如 JRockit(Oracle)、J9(IBM) 虚拟机有方法区 ,但是就没有永久代 PermGen space所以我们以下讨论的都是基于 HotSpot 虚拟机。详细回答再谈运行时内存从小刀前面写的文章中可以知道,方法区是运行时区域的一部分,且是各个线程共享内存的区域,它用于存储类的信息、常量、静态变量、即使时编译后的代码等数据。我们来看看这虚拟机内存的分布图:我们再来看看方法区这块内存的存储数据,如下:《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于 HotSpotJVM 而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。用大白话说就是,制定虚拟机规范的这批人觉得方法区因该是属于堆的,但是如果实现者嫌麻烦的话,在你自己的虚拟机实现里可以不把这部分当成堆永久代(PermGen)在jdk7及以前,HotSpot对方法区的实现是叫做永久代 Permanent Generation space。这里有个误区,很多人把 永久代等价于方法区,会说:“永久代就是方法区”,这样子表述不够精准。这里举个例子,在自然界中我们通过形态特征、栖息环境、生活习惯、分布范围、繁殖方式等特性来定义动物的类别。比如犬科动物的特征是“体形矫健,四肢细长,擅长跑,颜面部长,吻端突出,尾较粗长,尾毛一般浓密蓬松。。。”,但是我们不能说犬科是哈士奇或者犬科是中华田园犬。我们只能说哈士奇是犬科的一个品种。所以说在JDK1.7以前的HotSpot虚拟机和jdk8的虚拟机运行时内存的变化如下图:我们平时应该都见过 java.lang.OutOfMemoryError: PermGen space 这个异常。这个就是永久代内存空间不能瞒住内存分配要求,虚拟机抛出的一个异常。在jdk7以前可以通过如下两个参数调整永久代空间通过-xx:Permsize来设置永久代初始分配空间。默认值是20.75M。通过-XX:MaxPermsize来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M。public class OomMock {
public static void main(String[] args) {
URL url = null;
List
try {
url = new File("/tmp").toURI().toURL();
URL[] urls = {url};
while (true){
ClassLoader loader = new URLClassLoader(urls);
classLoaderList.add(loader);
loader.loadClass("com.example.modeldemo.A");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的例子如果是在Jdk7下运行会因为永久代内存分配不足而内存溢出。元空间(Metaspace)由上文可知,Metaspace(元空间)和 PermGen(永久代)都是对 JVM规范中方法区的一种落地实现只是 Oracle 从 JDK7 就开始就逐步的将永久代移除,慢慢的用元空间代替。直到JDK8 的发布才宣告 PermGen(永久代)的彻底移除。jdk7开始已经对字符串常量池等从永久代移除,所以永久代的移除过程跨越了jdk7和jdk8两个大版本。是渐进式的移除。接下来我们来看一个例子:import java.util.ArrayList;
import java.util.List;
public class StringOomMock {
static String base = "string";
public static void main(String[] args) {
List
for (int i=0;i< Integer.MAX_VALUE;i++){
String str = base + base;
base = str;
list.add(str.intern());
}
}
}
上面这个例子我们对一个类常量 base 不断的做字符串拼接在不同环境中遇到的情况如下:jdk6 的情况下:jdk7的情况下:jdk8的情况下:我们从上面姐结果克义得出以下几个结论在jdk6中抛出的是永久代异常,说明运行时常量池在永久代在jdk7和jdk8 抛出的是在堆异常,说明运行时常量池在java堆中在 jdk8 中有一条警告 ignoring option PermSize=10M; support was removed in 8.0 ..这表示 jdk8 已经不支持 PermSize=10M 这种配置来调节永久代大小元空间和永久代不同点内存位置:元空间和永久代最大的区别是元空间并不在虚拟机中,而是使用本地内存参数调配:永久代:通过-xx:Permsize来设置永久代初始分配空间。默认值是20.75M。-XX:MaxPermsize来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M。元空间:大小可以使用参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定,默认值依赖于平台。windows下,-XX:MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即没有限制异常溢出:元空间:如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出,虚拟机一样会抛出OutOfMemoryError:Metaspace。异常永久代:达内存配置上限抛出 OutOfMemoryError:PermGen space 异常为什么移除永久代我们来看看 openjdk文档里面的一句话:This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.大致意思就是说,为了 JRockit 和 Hotspot 融合工作,JRockit客户不需要配置永久代,因为JRockit没有永久代除了为了融合适配移除永久代以外还有其他原因:永久代设置空间大小是很难确定的,因为可能某个实际的业务场景中有不断的类加载等工作,但是元空间时使用本地内存,默认情况下时手本地大小限制的。调优困难,一般来说这个区域的回收效果比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不在使用的类型。我是小刀,今天就到这了,各位帅哥美女点点关注,给你最硬核的技术文章 原文地址:JVM方法区、永久代、元空间三者区别发布于 2022-04-26 18:51JavaJava 虚拟机(JVM)赞同 61 条评论分享喜欢收藏申请转载文章被以下专栏收录java虚拟机记录虚拟机相
深入探究JVM | 探秘Metaspace - 知乎
深入探究JVM | 探秘Metaspace - 知乎切换模式写文章登录/注册深入探究JVM | 探秘Metaspace大风起兮云飞扬Java 8彻底将永久代移除出了HotSpot JVM,将其原有的数据迁移至Java Heap或Metaspace。这一篇文章我们来总结一下Metaspace(元空间)的特性。如有错误,敬请指出,谢谢~引言:永久代为什么被移出HotSpot JVM了?在HotSpot JVM中,永久代中用于存放类和方法的元数据以及常量池,在Java中对应能通过反射获取到的数据,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。永久代是有大小限制的,因此如果加载的类太多,很有可能导致永久代内存溢出,即万恶的 java.lang.OutOfMemoryError: PermGen 。为此我们不得不对虚拟机做调优那么,Java 8中永久代为什么被移出HotSpot JVM了?详见:JEP 122: Remove the Permanent Generation原因主要有两个:1、由于Permanent Generation内存经常不够用或发生内存泄露,引发恼人的java.lang.OutOfMemoryError: PermGen (在Java Web开发中非常常见)。2、移除Permanent Generation可以促进HotSpot JVM与JRockit VM的融合,因为JRockit没有永久代。根据上面的各种原因,永久代最终被移除,方法区移至Metaspace,字符串常量移至Java Heap。探秘元空间由于Metaspace的资料比较少,这里主要是依据Oracle官方的Java虚拟机规范及Oracle Blog里的几篇文章来总结的。首先,Metaspace(元空间)是哪一块区域?官方的解释是:In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.也就是说,JDK 8开始把类的元数据放到本地堆内存(native heap)中,这一块区域就叫Metaspace,中文名叫元空间。1、优点使用本地内存有什么好处呢?最直接的表现就是OOM问题将不复存在,因为默认的类的元数据分配只受本地内存大小的限制,也就是说本地内存剩余多少,理论上Metaspace就可以有多大(貌似容量还与操作系统的虚拟内存有关?这里不太清楚),这解决了空间不足的问题。不过,让Metaspace变得无限大显然是不现实的,因此我们也要限制Metaspace的大小:使用-XX:MaxMetaspaceSize参数来指定Metaspace区域的大小。JVM默认在运行时根据需要动态地设置MaxMetaspaceSize的大小。除此之外,它还有以下优点:Take advantage of Java Language Specification property : Classes and associated metadata lifetimes match class loader’sLinear allocation onlyNo individual reclamation (except for RedefineClasses and class loading failure)No GC scan or compactionNo relocation for metaspace objects2、垃圾回收如果Metaspace的空间占用达到了设定的最大值,那么就会触发GC来收集死亡对象和类的加载器。根据JDK 8的特性,G1和CMS都会很好地收集Metaspace区(一般都伴随着Full GC)。为了减少垃圾回收的频率及时间,控制吞吐量,对Metaspace进行适当的监控和调优是非常有必要的。如果在Metaspace区发生了频繁的Full GC,那么可能表示存在内存泄露或Metaspace区的空间太小了。3、新增参数-XX:MetaspaceSize是分配给类元数据空间(以字节计)的初始大小(Oracle逻辑存储上的初始高水位,the initial high-water-mark ),此值为估计值。MetaspaceSize的值设置的过大会延长垃圾回收时间。垃圾回收过后,引起下一次垃圾回收的类元数据空间的大小可能会变大。-XX:MaxMetaspaceSize是分配给类元数据空间的最大值,超过此值就会触发Full GC,此值默认没有限制,但应取决于系统内存的大小。JVM会动态地改变此值。-XX:MinMetaspaceFreeRatio表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最小比例,不够就会导致垃圾回收。-XX:MaxMetaspaceFreeRatio表示一次GC以后,为了避免增加元数据空间的大小,空闲的类元数据的容量的最大比例,不够就会导致垃圾回收。4、监控与调优(待补充)VisualVM, jstat, jstack可以监测元空间的动态,后续将更新这里。参考资料The Java Virtual Machine Specification, Java SE 8 Edition, OracleMetaspace in Java 8What is the use of Metaspace in Java 8? - StackOverflowAbout G1 Garbage Collector, Permanent Generation and MetaspaceJEP 122: Remove the Permanent GenerationPermGen elimination in JDK 8 - StackOverflow发布于 2020-06-13 14:52Java 虚拟机(JVM)HotSpot VMJDK赞同 5添加评论分享喜欢收藏申请
JVM学习——元空间(Metaspace) - 简书
习——元空间(Metaspace) - 简书登录注册写文章首页下载APP会员IT技术JVM学习——元空间(Metaspace)高稷关注赞赏支持JVM学习——元空间(Metaspace)一、从方法区(PermGen)到元空间(Metaspace)方法区(PermGen)
JDK1.8以前的HotSpot JVM有方法区,也叫永久代(permanent generation)。
方法区用于存放已被虚拟机加载的类信息、常量、静态变量,即编译器编译后的代码。
方法区是一片连续的堆空间,通过-XX:MaxPermSize来设定永久代最大可分配空间,当JVM加载的类信息容量超过了这个值,会报OOM:PermGen错误。
永久代的GC是和老年代(old generation)捆绑在一起的,无论谁满了,都会触发永久代和老年代的垃圾收集。
JDK1.7开始了方法区的部分移除:符号引用(Symbols)移至native heap,字面量(interned strings)和静态变量(class statics)移至java heap。
为什么要用Metaspace替代方法区
随着动态类加载的情况越来越多,这块内存变得不太可控,如果设置小了,系统运行过程中就容易出现内存溢出,设置大了又浪费内存。
二、Metaspace的组成
Metaspace由两大部分组成:Klass Metaspace和NoKlass Metaspace。
Klass Metaspace
Klass Metaspace就是用来存klass的,就是class文件在jvm里的运行时数据结构(不过我们看到的类似A.class其实是存在heap里的,是java.lang.Class的对象实例)。
这部分默认放在Compressed Class Pointer Space中,是一块连续的内存区域,
紧接着Heap,和之前的perm一样。通过-XX:CompressedClassSpaceSize来控制这块内存的大小,默认是1G。
下图展示了对象的存储模型,_mark是对象的Mark Word,_klass是元数据指针
has ccs.jpg
Compressed Class Pointer Space不是必须有的,如果设置了-XX:-UseCompressedClassPointers,或者-Xmx设置大于32G,就不会有这块内存,这种情况下klass都会存在NoKlass Metaspace里。
no ccs.jpg
NoKlass Metaspace
NoKlass Metaspace专门来存klass相关的其他的内容,比如method,constantPool等,可以由多块不连续的内存组成。
这块内存是必须的,虽然叫做NoKlass Metaspace,但是也其实可以存klass的内容,上面已经提到了对应场景。
NoKlass Metaspace在本地内存中分配。
指针压缩
64位平台上默认打开
设置-XX:+UseCompressedOops压缩对象指针, oops指的是普通对象指针(ordinary object pointers), 会被压缩成32位。
设置-XX:+UseCompressedClassPointers压缩类指针,会被压缩成32位。
三、Metaspace内存管理
在metaspace中,类和其元数据的生命周期与其对应的类加载器相同,只要类的类加载器是存活的,在Metaspace中的类元数据也是存活的,不能被回收。
每个加载器有单独的存储空间。
省掉了GC扫描及压缩的时间。
当GC发现某个类加载器不再存活了,会把对应的空间整个回收。
Metaspace VM使用一个块分配器(chunking allocator)来管理Metaspace空间的内存分配。块的大小依赖于类加载器的类型。
Metaspace VM中有一个全局的可使用的块列表(a global free list of chunks)。当类加载器需要一个块的时候,类加载器从全局块列表中取出一个块,添加到它自己维护的块列表中。当类加载器死亡,它的块将会被释放,归还给全局的块列表。
块(chunk)会进一步被划分成blocks,每个block存储一个元数据单元(a unit of metadata)。Chunk中Blocks的是分配线性的(pointer bump)。这些chunks被分配在内存映射空间(memory mapped(mmapped) spaces)之外。在一个全局的虚拟内存映射空间(global virtual mmapped spaces)的链表,当任何虚拟空间变为空时,就将该虚拟空间归还回操作系统。
metachunks.jpg
上面这幅图展示了Metaspace使用metachunks在mmapeded virual spaces分配的情形。
四、metaspace的主要参数
MetaspaceSize
MaxMetaspaceSize
CompressedClassSpaceSize
MinMetaspaceExpansion
MaxMetaspaceExpansion
MinMetaspaceFreeRatio
MaxMetaspaceFreeRatio
UseLargePagesInMetaspace
InitialBootClassLoaderMetaspaceSize
MetaspaceSize
metaspaceGC发生的初始阈值,也是最小阈值,默认20.8M左右,与之对比的主要是指Klass Metaspace与NoKlass Metaspace两块committed的内存和。
触发metaspaceGC的阈值是不断变化的:当metaspace使用的内存接近阈值时,会尝试增大阈值。metaspaceGC后也会调整阈值。
MaxMetaspaceSize
由于metaspace大部分在本地内存中分配,默认基本是无穷大,但仍然受本地内存大小的限制。为了防止metaspace被无止境使用,建议设置这个参数。
这个参数会限制metaspace(包括了Klass Metaspace以及NoKlass Metaspace)被committed的内存大小,会保证committed的内存不会超过这个值,一旦超过就会触发GC。
和MaxPermSize的区别,根据MaxMetaspaceSize,并不会在jvm启动的时候分配一块这么大的内存出来,而根据MaxPermSize分配的内存则是固定大小。
CompressedClassSpaceSize
Compressed Class Pointer Space区域的大小,默认1G。
如果设置了-XX:-UseCompressedClassPointers,或者-Xmx设置大于32G,则这个参数不生效。
MinMetaspaceExpansion
MinMetaspaceExpansion和MaxMetaspaceExpansion这两个参数这两个参数和扩容其实并没有直接的关系,并不是为了增大committed的内存。
主要是在比较特殊的场景下救急使用,增大触发metaspace GC的阈值,延迟GC的发生。
默认332.8K,增大触发metaspace GC阈值的最小要求。
如果需要分配的内存小于MinMetaspaceExpansion,则将metaspace GC的阈值提升MinMetaspaceExpansion。
MaxMetaspaceExpansion
默认5.2M,增大触发metaspace GC阈值的最大要求。
如果需要分配的内存大于MinMetaspaceExpansion但是小于MaxMetaspaceExpansion,那增量就是MaxMetaspaceExpansion。
如果需要分配的内存超过了MaxMetaspaceExpansion,那增量就是MinMetaspaceExpansion加上要分配的内存大小
注:每次分配只会给对应的线程一次扩展触发metaspace GC阈值的机会,如果扩展了,但是还不能分配,那就只能等着做GC了。
MinMetaspaceFreeRatio
MinMetaspaceFreeRatio和下面的MaxMetaspaceFreeRatio,主要是影响触发metaspaceGC的阈值。
默认40,表示每次GC完之后,如果metaspace内存的空闲比例小于MinMetaspaceFreeRatio%,那么将尝试做扩容,增大触发metaspaceGC的阈值。
不过这个增量至少是MinMetaspaceExpansion才会做,不然不会增加这个阈值。
这个参数主要是为了避免触发metaspaceGC的阈值和gc之后committed的内存的量比较接近,于是将这个阈值进行扩大。
注:这里不用gc之后used的量来算,主要是担心可能出现committed的量超过了触发metaspaceGC的阈值,这种情况一旦发生会很危险,会不断做gc,这应该是jdk8在某个版本之后才修复的bug
MaxMetaspaceFreeRatio
默认70,这个参数和上面的参数基本是相反的,是为了避免触发metaspaceGC的阈值过大,而想对这个值进行缩小。
这个参数在gc之后committed的内存比较小的时候并且离触发metaspaceGC的阈值比较远的时候,调整会比较明显。
UseLargePagesInMetaspace
默认false,这个参数是说是否在metaspace里使用LargePage,一般情况下我们使用4KB的page size,这个参数依赖于UseLargePages这个参数开启,不过这个参数我们一般不开。
InitialBootClassLoaderMetaspaceSize
64位下默认4M,32位下默认2200K,metasapce前面已经提到主要分了两大块,Klass Metaspace以及NoKlass Metaspace,而NoKlass Metaspace是由一块块内存组合起来的,这个参数决定了NoKlass Metaspace的第一个内存Block的大小,即2*InitialBootClassLoaderMetaspaceSize,同时为bootstrapClassLoader的第一块内存chunk分配了InitialBootClassLoaderMetaspaceSize的大小
五、jstat里的metaspace字段
我们看GC是否异常,除了通过GC日志来做分析之外,我们还可以通过jstat这样的工具展示的数据来分析,前面我公众号里有篇文章介绍了jstat这块的实现,有兴趣的可以到我的公众号你假笨里去翻阅下jstat的这篇文章。
我们通过jstat可以看到metaspace相关的这么一些指标,分别是M,CCS,MC,MU,CCSC,CCSU,MCMN,MCMX,CCSMN,CCSMX
MC & MU & CCSC & CCSU
MC表示Klass Metaspace以及NoKlass Metaspace两者总共committed的内存大小,单位是KB,虽然从上面的定义里我们看到了是capacity,但是实质上计算的时候并不是capacity,而是committed,这个是要注意的
MU这个无可厚非,说的就是Klass Metaspace以及NoKlass Metaspace两者已经使用了的内存大小
CCSC表示的是Klass Metaspace的已经被commit的内存大小,单位也是KB
CCSU表示Klass Metaspace的已经被使用的内存大小
M & CCS
M表示的是Klass Metaspace以及NoKlass Metaspace两者总共的使用率,其实可以根据上面的四个指标算出来,即(CCSU+MU)/(CCSC+MC)
CCS表示的是NoKlass Metaspace的使用率,也就是CCSU/CCSC算出来的
PS:所以我们有时候看到M的值达到了90%以上,其实这个并不一定说明metaspace用了很多了,因为内存是慢慢commit的,所以我们的分母是慢慢变大的,不过当我们committed到一定量的时候就不会再增长了
MCMN & MCMX & CCSMN & CCSMX
MCMN和CCSMN这两个值可以忽略,一直都是0
MCMX表示Klass Metaspace以及NoKlass Metaspace两者总共的reserved的内存大小,比如默认情况下Klass Metaspace是通过CompressedClassSpaceSize这个参数来reserved 1G的内存,NoKlass Metaspace默认reserved的内存大小是2* InitialBootClassLoaderMetaspaceSize
CCSMX表示Klass Metaspace reserved的内存大小
参考资料
https://www.jianshu.com/p/92a5fbb33764
https://www.jianshu.com/p/1a0b4bf8d498
https://www.cnblogs.com/duanxz/p/3520829.html
©著作权归作者所有,转载或内容合作请联系作者 人面猴序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...沈念sama阅读 145,444评论 1赞 308死咒序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...沈念sama阅读 62,233评论 1赞 259救了他两次的神仙让他今天三更去死文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...开封第一讲书人阅读 96,492评论 0赞 214道士缉凶录:失踪的卖姜人 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...开封第一讲书人阅读 41,523评论 0赞 184港岛之恋(遗憾婚礼)正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...茶点故事阅读 49,386评论 1赞 262恶毒庶女顶嫁案:这布局不是一般人想出来的文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...开封第一讲书人阅读 39,048评论 1赞 179城市分裂传说那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...沈念sama阅读 30,636评论 2赞 276双鸳鸯连环套:你想象不到人心有多黑文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...开封第一讲书人阅读 29,406评论 0赞 171万荣杀人案实录序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...沈念sama阅读 32,769评论 0赞 215护林员之死正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...茶点故事阅读 29,477评论 2赞 220白月光启示录正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...茶点故事阅读 30,832评论 1赞 232活死人序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...沈念sama阅读 27,281评论 2赞 216日本核电站爆炸内幕正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...茶点故事阅读 31,774评论 3赞 214男人毒药:我在死后第九天来索命文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...开封第一讲书人阅读 25,689评论 0赞 9一桩弑父案,背后竟有这般阴谋文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...开封第一讲书人阅读 26,118评论 0赞 170情欲美人皮我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...沈念sama阅读 33,771评论 2赞 235代替公主和亲正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...茶点故事阅读 33,927评论 2赞 238推荐阅读更多精彩内容JVM源码分析之Metaspace解密概述 metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,...你假笨阅读 8,834评论 1赞 243.JVM系列-G1垃圾收集器目录 一、背景 二、G1垃圾收集器特性 三、G1执行步骤 四、G1基本参数 四、G1日志解释 六、基本原理 七、...爱吃糖果阅读 3,022评论 0赞 0JVM-MetaSpacejdk8里特有的数据结构用来替代perm metaspace其实由两大部分组成 Klass Metaspace, ...沉淀_0x0阅读 1,443评论 0赞 1JVM资料整理Java 虚拟机有自己完善的硬件架构, 如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 屏蔽了与具体操作系...尹小凯阅读 1,599评论 0赞 10HotSpot虚拟机在java 1.8中的新实现Java HotSpot 虚拟机是 Java SE 平台的一个核心组件。它实现 Java 虚拟机规范,并作为 Ja...大佛爱读书阅读 2,620评论 1赞 0评论3赞2020赞21赞赞赏更
Java 8: 元空间(Metaspace)_jdk8 元空间大小-CSDN博客
>Java 8: 元空间(Metaspace)_jdk8 元空间大小-CSDN博客
Java 8: 元空间(Metaspace)
最新推荐文章于 2024-01-12 00:12:50 发布
淡淡的倔强
最新推荐文章于 2024-01-12 00:12:50 发布
阅读量3.9w
收藏
65
点赞数
16
分类专栏:
JDK
JVM
文章标签:
java8
元空间
MetaSpace
JVM
永久代
JVM
同时被 2 个专栏收录
18 篇文章
1 订阅
订阅专栏
JDK
9 篇文章
2 订阅
订阅专栏
前言
很多开发者都在其系统中见过“java.lang.OutOfMemoryError: PermGen space”这一问题。这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的,通常出现于代码热部署时。相对于正式产品,该问题在开发机上出现的 频率更高,在产品中最常见的“问题”是默认值太低了。常用的解决方法是将其设置为256MB或更高。
JDK8 HotSpot JVM 将移除永久区,使用本地内存来存储类元数据信息并称之为:元空间(Metaspace)。这意味着不会再有java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用。
总结: PermGen空间状况:这部分内存空间将全部移除。JVM的参数:PermSize 和 MaxPermSize 会被忽略并给出警告(如果在启用时设置了这两个参数)。
Metaspace 容量:默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)。新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。
另外,对于僵死的类及类加载器的垃圾回收将在元数据使用达到“MaxMetaspaceSize”参数的设定值时进行。适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适。
PermGen space简单介绍
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。
JVM 种类有很多,比如 Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM等等。当然武林盟主是Hotspot了,这个毫无争议。需要注意的是,PermGen space是Oracle-Sun Hotspot才有,JRockit以及J9是没有这个区域。
元空间(Metaspace):一种新的内存空间的诞生
JDK8 HotSpot JVM 使用本地内存来存储类元数据信息并称之为:元空间(Metaspace);这与Oracle JRockit 和IBM J9很相似。如下图所示:
这将是一个好消息:意味着不会再有java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用……但请等等,这么说还为时过早。在默认情况下,这些改变是透明的,接下来我们的展示将使你知道仍然要关注类元数据内存的占用。请一定要牢记,这个新特性也不能神奇地消除类和类加载器导致的内存泄漏。
java8中metaspace总结如下:
PermGen 空间的状况:
这部分内存空间将全部移除。JVM的参数:PermSize 和 MaxPermSize 会被忽略并给出警告(如果在启用时设置了这两个参数)。
Metaspace 内存分配模型:
大部分类元数据都在本地内存中分配。用于描述类元数据的“klasses”已经被移除。
Metaspace 容量:
默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)。 新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。
Metaspace 垃圾回收:
对于僵死的类及类加载器的垃圾回收将在元数据使用到“MaxMetaspaceSize”参数的设定值时进行。 适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适。
Java 堆内存的影响:
一些杂项数据已经移到Java堆空间中。升级到JDK8之后,会发现Java堆 空间有所增长。
Metaspace 监控:
元空间的使用情况可以从HotSpot1.8的详细GC日志输出中得到。 Jstat 和 JVisualVM两个工具,在我们使用b75版本进行测试时,已经更新了,但是还是能看到老的PermGen空间的出现。 前面已经从理论上充分说明,下面让我们通过“泄漏”程序进行新内存空间的观察……
PermGen vs. Metaspace 运行时比较
为了更好地理解Metaspace内存空间的运行时行为, 将进行以下几种场景的测试: 1. 使用JDK1.7运行Java程序,监控并耗尽默认设定的85MB大小的PermGen内存空间。 2. 使用JDK1.8运行Java程序,监控新Metaspace内存空间的动态增长和垃圾回收过程。 3. 使用JDK1.8运行Java程序,模拟耗尽通过“MaxMetaspaceSize”参数设定的128MB大小的Metaspace内存空间。
首先建立了一个模拟PermGen OOM的代码
publicclassClassA {
publicvoidmethod(String name) {
// do nothing
}
}
上面是一个简单的ClassA,把他编译成class字节码放到D:/classes下面,测试代码中用URLClassLoader来加载此类型上面类编译成class
/**
* 模拟PermGen OOM
* @author benhail
*/
publicclassOOMTest {
publicstaticvoidmain(String[] args) {
try{
//准备url
URL url = newFile("D:/classes").toURI().toURL();
URL[] urls = {url};
//获取有关类型加载的JMX接口
ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
//用于缓存类加载器
List
while(true) {
//加载类型并缓存类加载器实例
ClassLoader classLoader = newURLClassLoader(urls);
classLoaders.add(classLoader);
classLoader.loadClass("ClassA");
//显示数量信息(共加载过的类型数目,当前还有效的类型数目,已经被卸载的类型数目)
System.out.println("total: "+ loadingBean.getTotalLoadedClassCount());
System.out.println("active: "+ loadingBean.getLoadedClassCount());
System.out.println("unloaded: "+ loadingBean.getUnloadedClassCount());
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
虚拟机器参数设置如下:-verbose -verbose:gc
设置-verbose参数是为了获取类型加载和卸载的信息
设置-verbose:gc是为了获取垃圾收集的相关信息
1.JDK 1.7 @64-bit – PermGen 耗尽测试 Java1.7的PermGen默认空间为85 MB(或者可以通过-XX:MaxPermSize=XXXm指定)
可以从上面的JVisualVM的截图看出:当加载超过6万个类之后,PermGen被耗尽。我们也能通过程序和GC的输出观察耗尽的过程。 程序输出(摘取了部分)
…… [Loaded ClassA from file:/D:/classes/] total: 64887 active: 64887 unloaded: 0 [GC 245041K->213978K(536768K), 0.0597188 secs] [Full GC 213978K->211425K(644992K), 0.6456638 secs] [GC 211425K->211425K(656448K), 0.0086696 secs] [Full GC 211425K->211411K(731008K), 0.6924754 secs] [GC 211411K->211411K(726528K), 0.0088992 secs] …………… java.lang.OutOfMemoryError: PermGen space
2.JDK 1.8 @64-bit – Metaspace大小动态调整测试
Java的Metaspace空间:不受限制 (默认)
从上面的截图可以看到,JVM Metaspace进行了动态扩展,本地内存的使用由20MB增长到646MB,以满足程序中不断增长的类数据内存占用需求。我们也能观察到JVM的垃圾 回收事件—试图销毁僵死的类或类加载器对象。但是,由于我们程序的泄漏,JVM别无选择只能动态扩展Metaspace内存空间。程序加载超过10万个 类,而没有出现OOM事件。
3.JDK 1.8 @64-bit – Metaspace 受限测试
Java的Metaspace空间:128MB(-XX:MaxMetaspaceSize=128m)
可以从上面的JVisualVM的截图看出:当加载超过2万个类之后,Metaspace被耗尽;与JDK1.7运行时非常相似。我们也能通过程序 和GC的输出观察耗尽的过程。另一个有趣的现象是,保留的原生内存占用量是设定的最大大小两倍之多。这可能表明,如果可能的话,可微调元空间容量大小策 略,来避免本地内存的浪费。
从Java程序的输出中看到如下异常。
[Loaded ClassA from file:/D:/classes/] total: 21393 active: 21393 unloaded: 0 [GC (Metadata GC Threshold) 64306K->57010K(111616K), 0.0145502 secs] [Full GC (Metadata GC Threshold) 57010K->56810K(122368K), 0.1068084 secs] java.lang.OutOfMemoryError: Metaspace
在设置了MaxMetaspaceSize的情况下,该空间的内存仍然会耗尽,进而引发“java.lang.OutOfMemoryError: Metadata space”错误。因为类加载器的泄漏仍然存在,而通常Java又不希望无限制地消耗本机内存,因此设置一个类似于MaxMetaspaceSize的限制看起来也 是合理的。
总结
1.之前不管是不是需要,JVM都会吃掉那块空间……如果设置得太小,JVM会死掉;如果设置得太大,这块内存就被JVM浪费了。理论上说,现在你完全可以不关注这个,因为JVM会在运行时自动调校为“合适的大小”; 2.提高Full GC的性能,在Full GC期间,Metadata到Metadata pointers之间不需要扫描了,别小看这几纳秒时间; 3.隐患就是如果程序存在内存泄露,像OOMTest那样,不停的扩展metaspace的空间,会导致机器的内存不足,所以还是要有必要的调试和监控。
原文地址:(https://my.oschina.net/benhaile/blog/214159)
优惠劵
淡淡的倔强
关注
关注
16
点赞
踩
65
收藏
觉得还不错?
一键收藏
知道了
0
评论
Java 8: 元空间(Metaspace)
前言 很多开发者都在其系统中见过“java.lang.OutOfMemoryError: PermGen space”这一问题。这往往是由类加载器相关的内存泄漏以及新类加载器的创建导致的,通常出现于代码热部署时。相对于正式产品,该问题在开发机上出现的 频率更高,在产品中最常见的“问题”是默认值太低了。常用的解决方法是将其设置为256MB或更高。 JDK8 HotSpot JVM 将移除永久
复制链接
扫一扫
专栏目录
Groovy大量计算导致oom的解决办法
05-27
问题原因分析:使用ScriptEngine.eval每次都会对脚本进行编译,生成一个新的类,被GroovyClassLoader加载,大量执行计算后,将导致被加载的类数量不断增加,最终OOM。
解决办法:对计算的表达式expression进行预编译,以表达式作为key,将编译好的类进行缓存,这样只会首次计算时去编译,后面再次计算时,根据expression从缓存里面取到对象,然后进行计算,不会再去创建类。
下载的资源文件中,封装了并发计算以及内存溢出解决方案的工具类GroovyEngine.java,调用示例:
GroovyEngine engine = GroovyEngine.getInstance();
engine.put("a",1);
engine.put("b",2);
Object v1 = engine.eval("sum(a,b)");
word源码java-ShangGuiGu-ZhouYang-JUC:周阳-juc
06-05
word源码java
java基础知识
复习java基础知识的笔记
进程和线程:
进程和线程主要区别在于他们是操作系统不同的资源管理方式.
进程是程序的一次执行过程(运行中的程序),是系统运行程序的基本单位.
一个进程至少包含一个线程(main),
可以包含多个线程.(换言之,线程是进程内的执行单元)
线程与进程相似,它是比进程更小的执行单位.一个进程在执行过程中可以产生多个线程.
同类线程有共享的堆和方法区(jdk8之后的元空间(MetaSpace)),
每个线程又有自己的程序计数器,虚拟机栈,本地方法栈.
系统在各个线程之间的切换工作要比进程负担低,因此线程又被称为轻量级进程
线程的几种状态:(见:jdk
Thread类源码中的state枚举类)
NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED
并发和并行:
并发是指计算机在同一时间段内处理多任务的执行.
如我和小明同时访问淘宝网站,那么淘宝服务器就同时处理我和小明的访问请求
并行是指多任务同时执行,但是任务之间没有任何关系,不涉及共享资源.
比如我一边看电视一边喝水,2件
参与评论
您还未登录,请先
登录
后发表或查看评论
JVM 元空间、java中的元空间
最新发布
LIJINGPO的博客
01-12
1154
上述运行结果可以看出,相同的代码,在JDK 1.6会出现“PermGen Space”的永久代内存溢出,而在JDK 1.7和JDK 1.8中,会出现"Java heap space"堆内存溢出,并且DK 1.8中 PermSize和MaxPermGen参数已经无效。因此,在JDK 1.7和JDK 1.8中,已经将字符串常量由永久代转移到堆中,并且JDK 1.8中已经完全移除了永久代,采用元空间来代替。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过运行参数来指定元空间的大小。
JDK8+Java+常用版本
10-26
说明
jdk8虽然出现很久了,但是可能我们还是有很多人并不太熟悉,本文主要就是介绍说明一些jdk8相关的内容。
主要会讲解:
lambda表达式
方法引用
默认方法
Stream
用Optional取代null
新的日志和时间
CompletableFuture
去除了永久代(PermGen) 被元空间(Metaspace)代替
java监控.rar
05-16
使用方法:
将jar包放置在运行java项目的机器上
运行指令
java -jar java_monitor-0.0.2-SNAPSHOT.jar --server.prot=8888
启动成功后访问默认端口8888
1.自定义端口
在执行jar包时追加参数
--server.port=9999
2.自定义监控周期
默认监控频率为60秒,并且只记录当天产生的监控数据。
如果需要自定义监控频率与监控时长,只需要在jar包所在目录下新建application.properties文件,修改下列字段即可
monitor.rate=60 #监控频率/秒
monitor.cron=0 0 0 * * ? #每日的0:00:00时刻清空数据
连续监控1个月,示例
monitor.cron=0 0 0 1 * ?
连续监控1年,示例
monitor.cron=0 0 0 1 1 ? *
不新建文件,使用追加参数的方法也是可以的。
3.监控参数
监控参数的含义如下:
S0C:s0(from)的大小(KB)
S1C:s1(from)的大小(KB)
S0U:s0(from)已使用的空间(KB)
S1U:s1(from)已经使用的空间(KB)
EC:eden区的大小(KB)
EU:eden区已经使用的空间(KB)
OC:老年代大小(KB)
OU:老年代已经使用的空间(KB)
MC:元空间的大小(Metaspace)
MU:元空间已使用大小(KB)
CCSC:压缩类空间大小(compressed class space)
CCSU:压缩类空间已使用大小(KB)
YGC:新生代gc次数
YGCT:新生代gc耗时(秒)
FGC:Full gc次数
FGCT:Full gc耗时(秒)
GCT:gc总耗时(秒)
Loaded:表示载入了类的数量
Unloaded 表示卸载类的数量
Compiled 表示编译任务执行的次数
Failed表示编译失败的次数
total:线程总数
RUNNABLE:正在运行的线程数
TIMED_WAITING:休眠的线程数
WAITING:等待的线程数
java8源码-jvm-study:jvm-study
06-04
java8
源码
jvm-study
方法执行过程
jvm申请内存
初始化运行时数据区
方法区:存放
class;静态变量:常量
堆:实例对象
栈:栈帧(对象的引用,方法)
类加载
执行方法
创建对象
堆空间分代划分
outOfMemory异常
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
可以看jvm参数查看网址
Direct
buffer
memory
:
直接内存太大(-XX:MaxDirectMemorySize=100m)
Java
heap
space:
堆内存溢出
(-Xms30m
-Xmx30m
-XX:+PrintGCDetails)
GC
overhead
limit
exceeded:
gc占用98%的资源回收效率不足2%的(-Xms30m
-Xmx30m)
Metaspace:方法区异常----(XX:MetaspaceSize=10M
-XX:MaxMetaspaceSize=10M)
常量池(方法区)
class常量池
class的方法
字面量(String
a
=
JAVA8 Metaspace内容_JDK8 metaspace调优
weixin_36477469的博客
02-26
497
从JDK8开始,永久代(PermGen)的概念被废弃掉了,取而代之的是一个称为Metaspace的存储空间。Metaspace使用的是本地内存,而不是堆内存,也就是说在默认情况下Metaspace的大小只与本地内存大小有关。当然你也可以通过以下的几个参数对Metaspace进行控制:-XX:MetaspaceSize=N这个参数是初始化的Metaspace大小,该值越大触发MetaspaceGC的...
Jvm(二)
qq_47375994的博客
07-16
967
这章讲述了JVM虚拟机类加载、对象分配、垃圾回收算法、垃圾回收器
JDK8 元空间
weixin_30443731的博客
03-27
260
1. 运行时常量池和静态变量都存储到了堆中,MetaSpace存储类的元数据,MetaSpace直接申请在本地内存中(Native memory),这样类的元数据分配只受本地内存大小的限制,OOM问题就不存在了。除此之外,还有其他很多好处:
2. 其实,移除永久代的工作从JDK1.7就开始了。JDK1.7中,存储在永久代的部分数据就已经转移到了Java Heap或者是 Native Heap。但...
-XX:MetaspaceSize和-XX:MaxMetaspaceSize配合使用
热门推荐
绅士jiejie的博客
10-10
1万+
-XX:MetaspaceSize:设置元空间大小
-XX:MaxMetaspaceSize:设置元空间最大大小
Java8以后,永久代被元空间取代,同时元空间不像永久代一样受制于堆内存,元空间是基于操作系统内存的,理论上讲,可以一直扩展内存直到操作系统的极限,所以设置元空间大小时,建议加上-XX:MaxMetaspaceSize参数,给个范围限制,和-XX:MetaspaceSize参数值一样,一般设置成256M即可,避免元空间占用的内存一直增长。
...
JavaDemo:记录 Java 的学习经历
04-27
使用元空间(MetaSpace)-> 直接使用物理内存 -> 加载类文件 代码更少(增加了新的语法Lambda表达式) 强大的Stream API 便于并行 增加了Optional容器类,最大化减少空指针异常 Lambda 表达式 Lambda 是一个匿名函数...
Pytorch机器学习/深度学习代码笔记
Nagato_Yuki_SOS的博客
12-03
802
Dataset
Dataset是一个抽象类,可以自定义数据集,为了能够方便的读取,需要将要使用的数据包装为Dataset类。
自定义的Dataset需要继承它并且实现两个成员方法:
1.getitem():该方法定义用索引(0到len(self))获取一条数据或一个样本。
2.len()方法返回数据集的总长度。
DataLoad
DataLoad提供了对Dataset的读取操作,常用参数有:Dataset数据集实例,batch_size(每个batch的大小,shuffle(是否进行搅乱操作),num_wo
JVM内存调优总结(JDK8)
weixin_38312719的博客
05-17
1355
说明:转载本人掘金文章 https://juejin.cn/post/7094613544687108126
内存分配
查看内存分配情况
1.查看堆总内存 jinfo -flag MaxHeapSize vmid
2.查看新生代内存 jinfo -flag NewSize vmid
3.查看老年代内存 jinfo -flag OldSize vmid
4.查看使用的垃圾收集器 jinfo -flags vmid
5.查看元空间(方法区)内存 jinfo -flag MetaspaceSize(MaxMet
Java中的元空间(Metaspace)
个人专长:数据结构和算法、大数据、数据库、主流框架
03-02
4292
元空间Metaspace
元空间、Full GC、内存调优
JinXYan的博客
05-05
3994
方法区和永久代的关系
在Java虚拟机规范中,方法区在虚拟机启动的时候创建,虽然方法区是堆的逻辑组成部分,但是简单的虚拟机实现可以选择不在方法区实现垃圾回收与压缩。这个版本的虚拟机规范也不限定实现方法区的内存位置和编译代码的管理策略。所以不同的JVM厂商,针对自己的JVM可能有不同的方法区实现方式。
在HotSpot中,设计者将方法区纳入GC分代收集。HotSpo...
终于讲清楚了:fullgc会回收方法区(元空间)吗
当我谈编程时我谈些什么
07-19
4816
先说结论:会。
原理解析:
1、首先方法区和元空间不是一个维度的概念。
在1.7中存在方法区,。
在1.8中新增了元空间,方法区移到了元空间。
根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。
方法区(线程共享)
被所有方法线程共享的一块内存区域。
主要用于存储类的信息、常量池、方法数据、方法代码等。
这个区域的内存回收目标主要针对常量池的回收和堆类型的卸载。
2、1.8中的元空间
元空间的特点:
1,每个加载器有专门的存储空间。
2,.
weblogic12c 设置jvm大小_JVM参数最佳实践:元空间的初始大小和最大大小
weixin_34893555的博客
12-03
500
本文阅读时间大约4分钟。JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代。永久代和元空间保存的数据并不完全一样,永久代中还保存另一些与类的元数据无关的杂项。如我们之前的一篇文章016:字符串对象在JVM中是如何存放的中说的,在Java 7里...
JVM-方法区(元空间)
liming0025的专栏
11-23
878
一、栈、堆、方法区的交互关系
从线程共享与否的角度来看:
下面一个简单的图示,说明了栈、堆、方法区之间关系:
person 对象的引用存放在栈中
new Person() 对象本身存放在堆中
Person 生成的结构,class文件存放在方法区
二、方法区的理解
方法区是线程共享的,存放的java文件编译后的指令(class)。
尽管所有方法区在逻辑上都属于堆的一部分,但一些简单的实现可能不会选择去进行GC或者进行压缩。但是HtoSpotJVM,把方法区叫做Non-Heap,目..
java.lang.outofmemoryerror: metaspace
06-06
java.lang.outofmemoryerror: metaspace是Java虚拟机在元空间(Metaspace)中无法分配更多内存时抛出的错误。元空间是Java虚拟机中用于存储类元数据的区域,包括类的名称、方法、字段等信息。当加载大量类或者动态生成类时,元空间的内存可能会被耗尽,导致该错误的发生。解决方法包括增加元空间的大小、减少类的加载或者优化代码等。
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
淡淡的倔强
CSDN认证博客专家
CSDN认证企业博客
码龄10年
暂无认证
115
原创
3万+
周排名
218万+
总排名
103万+
访问
等级
9257
积分
271
粉丝
313
获赞
88
评论
1147
收藏
私信
关注
热门文章
Docker每次启动容器,IP及hosts指定
78295
SpringBoot @ComponentScan 作用
51087
Java 8: 元空间(Metaspace)
39579
Spring方法拦截器MethodInterceptor
36940
SpringBoot系列(二)指定内置tomcat版本
30927
分类专栏
多线程
21篇
java基础篇
13篇
java深入篇
12篇
Spring
11篇
React
2篇
Mybatis
1篇
JDK
9篇
Redis
8篇
MySql
3篇
Linux
11篇
工具类
2篇
架构设计
6篇
数据结构
2篇
JVM
18篇
Zookeeper
7篇
Docker
13篇
web
3篇
算法
3篇
计算机组成原理
1篇
NIO
13篇
maven
6篇
微服务
4篇
spring-boot
19篇
网络编程
5篇
Scala
3篇
Spark
30篇
推荐
1篇
人工智能
7篇
Hadoop
6篇
Hive
5篇
Sqoop
1篇
Flume
1篇
Kafka
2篇
Hbase
4篇
Elasticsearch
12篇
最新评论
Hadoop系列(一)Docker部署Hadoop集群
whatchinaname:
Step 8/12 : RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
---> Running in daf361ee5feb
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase):
我再这里卡住了,回车不行,输入密码也不行
JVM命令-jstat
弹性思索:
单位应该是kb 不是字节吧
hadoop关不掉namenode的解决办法
modaciv:
可以的,有用!
Spring方法拦截器MethodInterceptor
努力搬砖的小贠:
不加配置的代码就是i耍流氓
java.lang包介绍
weixin_38730047:
谢谢了,省了我很多力
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
Spring源码-循环依赖与三级缓存
LRU算法的Java实现
MySQL-MVCC机制
2020年17篇
2019年11篇
2018年126篇
2017年90篇
目录
目录
分类专栏
多线程
21篇
java基础篇
13篇
java深入篇
12篇
Spring
11篇
React
2篇
Mybatis
1篇
JDK
9篇
Redis
8篇
MySql
3篇
Linux
11篇
工具类
2篇
架构设计
6篇
数据结构
2篇
JVM
18篇
Zookeeper
7篇
Docker
13篇
web
3篇
算法
3篇
计算机组成原理
1篇
NIO
13篇
maven
6篇
微服务
4篇
spring-boot
19篇
网络编程
5篇
Scala
3篇
Spark
30篇
推荐
1篇
人工智能
7篇
Hadoop
6篇
Hive
5篇
Sqoop
1篇
Flume
1篇
Kafka
2篇
Hbase
4篇
Elasticsearch
12篇
目录
评论
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
添加红包
祝福语
请填写红包祝福语或标题
红包数量
个
红包个数最小为10个
红包总金额
元
红包金额最低5元
余额支付
当前余额3.43元
前往充值 >
需支付:10.00元
取消
确定
下一步
知道了
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝
规则
hope_wisdom 发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
0
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。
余额充值
JAVA8 JVM的变化: 元空间(Metaspace)-腾讯云开发者社区-腾讯云
8 JVM的变化: 元空间(Metaspace)-腾讯云开发者社区-腾讯云哲洛不闹JAVA8 JVM的变化: 元空间(Metaspace)关注作者腾讯云开发者社区文档建议反馈控制台首页学习活动专区工具TVP最新优惠活动文章/答案/技术大牛搜索搜索关闭发布登录/注册首页学习活动专区工具TVP最新优惠活动返回腾讯云官网哲洛不闹首页学习活动专区工具TVP最新优惠活动返回腾讯云官网社区首页 >专栏 >JAVA8 JVM的变化: 元空间(Metaspace)JAVA8 JVM的变化: 元空间(Metaspace)哲洛不闹关注发布于 2018-09-14 10:24:395K0发布于 2018-09-14 10:24:39举报文章被收录于专栏:java一日一条java一日一条本文将会分享至今为至我收集的关于永久代(Permanent Generation )的替代者:元空间(Metaspace)的信息。我也会比较在执行JAVA 程序时HotSpot 1.7 和 HotSpot 1.8 (b75)的运行行为。关于元空间(Metaspace)最后的规范、调整参数和文档将在Java 8 正式发布之后公开。元空间(Metaspace):一个新的内存空间的诞生.与 Oracle JRockit 和 IBM JVM类似,JDK 8.HotSpot JVM开始使用本地化的内存存放类的元数据,这个空间叫做元空间(Metaspace)。一个好的消息是意味着java.lang.OutOfMemoryError: PermGen的空间问题将不复存在,并且不再需要调整和监控这个内存空间,虽然还没有那么快。当这个变化被默认执行的时候,我们会发现你任然需要担心类的元数据的内存占用率的问题,所以请记住这个新的特性并不会奇迹般的消除类和类加载器的内存泄漏。而是你需要使用一些不同的方式和学习新名词来追查这些问题。 总结:永久区这个内存空间被完全的移除 ,JVM参数PermSize 和 MaxPermSize会被忽略,当前在启动时会有警告信息元空间(Metaspace)内存分配模型。现在大多数的类元数据分配在本地化内存中。我们用来描述类的元数据的klasses已经被移除。 元空间的容量 默认情况下,类元数据分配受到可用的本机内存容量的限制(容量依然取决于你使用32位JVM还是64位操作系统的虚拟内存的可用性)。 一个新的参数 (MaxMetaspaceSize)可以使用。允许你来限制用于类元数据的本地内存。如果没有特别指定,元空间将会根据应用程序在运行时的需求动态设置大小。 元空间的垃圾回收如果类元数据的空间占用达到参数“MaxMetaspaceSize”设置的值,将会触发对死亡对象和类加载器的垃圾回收。 为了限制垃圾回收的频率和延迟,适当的监控和调优元空间是非常有必要的。元空间过多的垃圾收集可能表示类,类加载器内存泄漏或对你的应用程序来说空间太小了。java堆空间的影响 一些各种各样的数据已经转移到Java堆空间。这意味着JDK8升级后,您可能会发现Java堆空间的不断增加。元空间监控 元空间的使用从HotSpot 1.8开始有详细的GC日志输出。在我们基于B75测试的时候Jstat 和JVisualVM还没有升级, 目前还是引用到老的永久代空间。现在有足够的理论,我们可以通过我们的Java程序泄漏的行为来观察我们的这个新的内存空间...永久代和元空间运行时对照:为了更好的理解新的元空间运行时的行为特征,我们创建一个类元数据泄露的java程序,你可以在这里下载源代码:我们测试下面的场景:使用JDK 1.7运行java程序,并且为了监控和耗尽永久代内存空间,将其设置为128MB使用JDK1.8(B75)运行java程序,并且监控新的元空间内存的冬天增长和垃圾回收。 使用JDK1.8(B75)运行java程序,通过设置MaxMetaspaceSize 为128MB来同样耗尽元空间 .JDK 1.7 @64-bit – PermGen depletionjava程序设置50k次的迭代 java的堆空间为1024MBjava的永久代空间为128MB (-XX:MaxPermSize=128m)正如你看到的JVisualVM的报告,当加载30K+ 的类的时候,永久代被耗尽。我们也可以从程序和GC的输出文件中发现耗尽。类元数据泄漏模拟器的作者Pierre-Hugues Charbonneau在博客: http://javaeesupportpatterns.blogspot.com中描述了错误: ERROR: java.lang.OutOfMemoryError: PermGen space 。现在我们使用 HotSpot JDK 1.8 JRE.来运行程序。 JDK 1.8 @64-bit – Metaspace dynamic re-sizeJava 程序设置50k次的迭代 Java 堆空间为1024MB Java 元空间为无限(默认值) 正如你看到的详细的GC输出,为了满足我们的Java程序不断增加的类元数据的内存占用,JVM元空间扩大从20 MB动态占用本机内存高达328 MB。我们也可以观察垃圾收集,JVM在试图摧毁任何死类或类加载器对象。自从我们的Java程序泄漏,JVM不得不扩张元空间的内存空间。该方案可以迭代50K次,并且没有OOM事件和加载50K+类。接下去我们来看最后的测试场景:JDK 1.8 @64-bit – Metaspace depletionJava 程序设置50k次的迭代Java 堆空间为1024MB Java 元空间为128 MB (-XX:MaxMetaspaceSize=128m)正如你看到的JVisualVM的报告,当加载30K+ 的类的时候,元空间被耗尽,和在JDK1.7的表现非常相近。我们也可以在程序和GC的输出日志中找到。另一个有趣的现象是,本机内存保留的占用空间是指定的最大大小的两倍之多。如果可能的话,为了避免本机内存浪费。这可能表明需要优化元空间扩张尺寸的策略,。 现在我们可以从java程序的输出日志中找到下面的异常:ERROR: java.lang.OutOfMemoryError: Metadata space正如预期的那样,设置元空间最大尺寸为128 MB,就像我们在JDK1.7中一样没有让我们完成我们的50K迭代的计划。JVM抛出一个新的OOM错误。上述OOM事件是由JVM从元空间在捕获一个一个内存分配失败后抛出。 metaspace.cpp 结束语 我希望你能欣赏这个对新的Java8元空间的早期的分析和实验 。目前观测表明,为了远离类似在我们最后测试场景中出现的频繁的元空间GC和OOM的问题,适当的监控和调优是必须的。以后的文章中可能包括性能比较,以确定这一新功能相关的潜在性能改进。请随时提供任何意见。本文参与 腾讯云自媒体分享计划,分享自微信公众号。原始发表:2018-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除javajvmasporaclejdk本文分享自 java一日一条 微信公众号,前往查看如有侵权,请联系 cloudcommunity@tencent.com 删除。本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!javajvmasporaclejdk评论登录后参与评论0 条评论热度最新登录 后参与评论推荐阅读LV.关注文章0获赞0领券社区专栏文章阅读清单互动问答技术沙龙技术视频团队主页腾讯云TI平台活动自媒体分享计划邀请作者入驻自荐上首页技术竞赛资源技术周刊社区标签开发者手册开发者实验室关于社区规范免责声明联系我们友情链接腾讯云开发者扫码关注腾讯云开发者领取腾讯云代金券热门产品域名注册云服务器区块链服务消息队列网络加速云数据库域名解析云存储视频直播热门推荐人脸识别腾讯会议企业云CDN加速视频通话图像分析MySQL 数据库SSL 证书语音识别更多推荐数据安全负载均衡短信文字识别云点播商标注册小程序开发网站监控数据迁移Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有 深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档Copyright © 2013 - 2024 Tencent Cloud.All Rights Reserved. 腾讯云 版权所有登录 后参与评论00深入理解JVM:元空间大小详细解析-腾讯云开发者社区-腾讯云
JVM:元空间大小详细解析-腾讯云开发者社区-腾讯云程序员追风深入理解JVM:元空间大小详细解析原创关注作者腾讯云开发者社区文档建议反馈控制台首页学习活动专区工具TVP最新优惠活动文章/答案/技术大牛搜索搜索关闭发布登录/注册首页学习活动专区工具TVP最新优惠活动返回腾讯云官网程序员追风首页学习活动专区工具TVP最新优惠活动返回腾讯云官网社区首页 >专栏 >深入理解JVM:元空间大小详细解析深入理解JVM:元空间大小详细解析原创程序员追风关注修改于 2019-10-12 10:22:232.5K0修改于 2019-10-12 10:22:23举报文章被收录于专栏:Java架构学习路线Java架构学习路线前言JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代。永久代和元空间保存的数据并不完全一样,永久代中还保存另一些与类的元数据无关的杂项。在Java 7里将字符串常量从永久代移动到了堆区域,但是永久代并没有完全改造完成。直到Java 8,永久代的改造才算完全搞定,在元空间中保存的数据比永久代中纯粹很多,就是类的元数据,这些信息只对编译期或JVM的运行时有用。理论学习使用Java 8以后,关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N,对于64位JVM来说,元空间的默认初始大小是20.75MB,默认的元空间的最大值是无限。MaxMetaspaceSize用于设置metaspace区域的最大值,这个值可以通过mxbean中的MemoryPoolBean获取到,如果这个参数没有设置,那么就是通过mxbean拿到的最大值是-1,表示无穷大。由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M(PS:读者可以根据自己的实际情况再调整)。欢迎大家关注我的公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。源码分析MetaspaceSize表示metaspace首次使用不够而触发FGC的阈值,只对触发起作用,原因是:垃圾搜集器内部是根据变量 _capacity_until_GC来判断metaspace区域是否达到阈值的,初始化代码如下所示:void MetaspaceGC::initialize() {// Set the high-water mark to MaxMetapaceSize during VM initializaton since
// we can't do a GC during initialization.
_capacity_until_GC = MaxMetaspaceSize;
} 复制GC收集器会在发生对metaspace的回收会,会计算新的capacityuntil_GC值,以后发生FGC就跟MetaspaceSize没有关系了。如果不设置MetaspaceSize,则默认的capacityuntil_GC为20M左右,具体代码如下:最后欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持! 原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。如有侵权,请联系 cloudcommunity@tencent.com 删除。jvmjava原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。如有侵权,请联系 cloudcommunity@tencent.com 删除。jvmjava评论登录后参与评论0 条评论热度最新登录 后参与评论推荐阅读LV.关注文章0获赞0目录前言理论学习源码分析最后领券社区专栏文章阅读清单互动问答技术沙龙技术视频团队主页腾讯云TI平台活动自媒体分享计划邀请作者入驻自荐上首页技术竞赛资源技术周刊社区标签开发者手册开发者实验室关于社区规范免责声明联系我们友情链接腾讯云开发者扫码关注腾讯云开发者领取腾讯云代金券热门产品域名注册云服务器区块链服务消息队列网络加速云数据库域名解析云存储视频直播热门推荐人脸识别腾讯会议企业云CDN加速视频通话图像分析MySQL 数据库SSL 证书语音识别更多推荐数据安全负载均衡短信文字识别云点播商标注册小程序开发网站监控数据迁移Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有 深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档Copyright © 2013 - 2024 Tencent Cloud.All Rights Reserved. 腾讯云 版权所有登录 后参与评论00