OutOfMemoryError系列(4): Metaspace

简介: 这是本系列的第四篇文章, 相关文章列表: OutOfMemoryError系列(1): Java heap spaceOutOfMemoryError系列(2): GC overhead limit exceededOutOfMemoryError系列(3): Permgen spaceOutOfMemoryError系列(4): MetaspaceJVM限制了Java程序的最大内存, 修改/指定启动参数可以改变这种限制。

这是本系列的第四篇文章, 相关文章列表:

JVM限制了Java程序的最大内存, 修改/指定启动参数可以改变这种限制。Java将堆内存划分为多个部分, 如下图所示:

04_01_OOM-example-metaspace.png

【Java8及以上】这些内存池的最大值, 由 -Xmx-XX:MaxMetaspaceSize 等JVM启动参数指定. 如果没有明确指定, 则根据平台类型(OS版本+JVM版本)和物理内存的大小来确定。

java.lang.OutOfMemoryError: Metaspace 错误所表达的信息是: 元数据区(Metaspace) 已被用满

原因分析

如果你是Java老司机, 应该对 PermGen 比较熟悉. 但从Java 8开始,内存结构发生重大改变, 不再使用Permgen, 而是引入一个新的空间: Metaspace. 这种改变基于多方面的考虑, 部分原因列举如下:

  • Permgen空间的具体多大很难预测。指定小了会造成 java.lang.OutOfMemoryError: Permgen size 错误, 设置多了又造成浪费。

  • 为了 GC 性能 的提升, 使得垃圾收集过程中的并发阶段不再 停顿, 另外对 metadata 进行特定的遍历(specific iterators)。

  • G1垃圾收集器 的并发 class unloading 进行深度优化。

在Java8中,将之前 PermGen 中的所有内容, 都移到了 Metaspace 空间。例如: class 名称, 字段, 方法, 字节码, 常量池, JIT优化代码, 等等。

Metaspace 的使用量与JVM加载到内存中的 class 数量/大小有关。可以说, java.lang.OutOfMemoryError: Metaspace 错误的主要原因, 是加载到内存中的 class 数量太多或者体积太大

示例

上一章的PermGen 类似, Metaspace 空间的使用量, 与JVM加载的 class 数量有很大关系。下面是一个简单的示例:

public class Metaspace {
  static javassist.ClassPool cp = javassist.ClassPool.getDefault();

  public static void main(String[] args) throws Exception{
    for (int i = 0; ; i++) { 
      Class c = cp.makeClass("eu.plumbr.demo.Generated" + i).toClass();
    }
  }
}

可以看到, 使用 javassist 工具库生成 class 那是非常简单。在 for 循环中, 动态生成很多class, 最终将这些class加载到 Metaspace 中。

执行这段代码, 随着生成的class越来越多, 最后将会占满 Metaspace 空间, 抛出 java.lang.OutOfMemoryError: Metaspace. 在Mac OS X上, Java 1.8.0_05 环境下, 如果设置了启动参数 -XX:MaxMetaspaceSize=64m, 大约加载 70000 个class后JVM就会挂掉。

解决方案

如果抛出与 Metaspace 有关的 OutOfMemoryError , 第一解决方案是增加 Metaspace 的大小. 使用下面这样的启动参数:

-XX:MaxMetaspaceSize=512m

这里将 Metaspace 的最大值设置为 512MB, 如果没有用完, 就不会抛出 OutOfMemoryError

有一种看起来很简单的方案, 是直接去掉 Metaspace 的大小限制。 但需要注意, 不限制Metaspace内存的大小, 假若物理内存不足, 有可能会引起内存交换(swapping), 严重拖累系统性能。 此外,还可能造成native内存分配失败等问题。

在现代应用集群中,宁可让应用节点挂掉, 也不希望其响应缓慢。

如果不想收到报警, 可以像鸵鸟一样, 把 java.lang.OutOfMemoryError: Metaspace 错误信息隐藏起来。 但这不能真正解决问题, 只会推迟问题爆发的时间。 如果确实存在内存泄露, 请参考前面的文章, 认真寻找解决方案。

原文链接: https://plumbr.eu/outofmemoryerror/permgen-space

翻译日期: 2017年9月19日

翻译人员: 铁锚: http://blog.csdn.net/renfufei

目录
相关文章
|
9月前
|
JSON API 数据格式
携程网获取景点列表 API 接口(携程 API 系列)
携程作为国内知名的在线旅游服务提供商,其景点列表API对接口功能、参数和返回格式进行了详细定义。该接口可获取景点基本信息(名称、地区、开放时间等),支持条件筛选查询(如按地区、评分、价格区间等)。接口返回JSON或XML格式数据,并设有调用限制以确保系统稳定性和数据安全。虽然携程未公开免费API,开发者可通过商务合作申请权限。以下为模拟Python请求示例,展示了如何使用该接口获取景点信息。 代码示例中,通过`requests.get()`发送GET请求,设置请求参数(如地区、门票价格等)和请求头(模拟浏览器访问),并处理响应数据。实际应用需替换为真实的接口URL,并遵循携程官方文档要求。
1819 0
|
11月前
|
Python
按条件将Excel文件拆分到不同的工作表
使用Python的pandas库,可以轻松将Excel文件按条件拆分到不同的工作表中。本文通过一个示例代码展示了如何生成一个包含总成绩表和三个班级表的Excel文件。代码首先创建了一个包含学生姓名、班级和各科成绩的数据框,然后按班级分组,将每个班级的数据分别写入不同的工作表。最后,生成的Excel文件将包含四个工作表,分别为总成绩表和三个班级的成绩表。
201 6
按条件将Excel文件拆分到不同的工作表
|
Java 索引
Java“ExceptionInInitializerError”解决
Java中遇到“ExceptionInInitializerError”错误通常是因为静态初始化块或静态变量初始化时发生异常。解决方法包括检查静态代码块中的逻辑错误、确保资源正确加载以及处理可能的空指针异常。
2067 8
|
安全 关系型数据库 分布式数据库
PolarDB 的安全性和合规性措施
【8月更文第27天】随着云计算技术的不断发展,企业对云数据库的安全性和合规性的需求日益增长。阿里云的 PolarDB 作为一款高度兼容 MySQL、PostgreSQL 和 Oracle 的关系型数据库服务,提供了强大的安全保护和合规性支持。本文将详细探讨 PolarDB 如何确保数据安全,并符合各种法规要求。
451 0
|
人工智能 机器人
多模态大模型活动 | 使用 PAI×LLaMA Factory 搭建文旅问答机器人
LLaMA Factory 是一款开源低代码大模型微调框架,集成了业界最广泛使用的微调技术,支持通过 Web UI 界面零代码微调大模型,目前已经成为开源社区内最受欢迎的微调框架,GitHub 星标超过3万。本次活动通过 PAI×LLaMA Factory 微调 Qwen2-VL 模型,快速搭建文旅领域知识问答机器人,期待看到您与 AI 导游的创意对话!
|
弹性计算 JavaScript 安全
ROS CDK魔法书:建立你的游戏王国(Java篇)
本文介绍了如何使用阿里云资源编排服务(ROS)的云开发套件(CDK)将2048小游戏部署到云端。ROS CDK允许使用编程语言定义和部署云资源,简化开发流程。ECS(弹性计算服务)提供灵活的计算资源,确保应用稳定运行。通过初始化工程项目、安装依赖、添加资源等步骤,可以轻松实现游戏的云端部署。文中详细描述了各步骤的操作方法及注意事项,帮助读者顺利完成部署。最后,通过简单命令即可删除资源栈,实现资源的高效管理。
ROS CDK魔法书:建立你的游戏王国(Java篇)
|
Unix Linux 开发工具
vim快捷键大全(表格形式)
vim快捷键大全(表格形式)
403 0
|
监控 网络协议 NoSQL
java线上排查OOM内存溢出
java线上排查OOM内存溢出
911 1
Xmind2022最新版破解与激活教程,操作简单
Xmind 是一款 全功能 的思维导图和头脑风暴软件。像大脑的瑞士军刀一般,助你理清思路,捕捉创意。
4138 0