[转帖]JVM metaspace outofmemory

jvm,metaspace,outofmemory · 浏览次数 : 0

小编点评

**Code Size:** 47,508,830 bytes **Methods:** * `breakpointInfo::set(Method*)`: Sets breakpoint information for a method. * `JvmtiBreakpoint::each_method_version_do(void (Method::*)(int))`: Iterates over method versions for a breakpoint. * `VM_Operation::evaluate()`: Evaluates a VM operation. * `VMThread::evaluate_operation(VM_Operation*)`: Evaluates an operation on a VM thread. * `VMThread::loop()+0x1ceV`: Loops through a VM thread. * `VMThread::run()+0x70V`: Runs a VM thread. * `java_start(Thread*)`: Starts a Java thread. **Other Data:** * `Date:** Mon Sep 25 14:30:30 CST 2017 * `File size:** 56.1 MB * `Number of classes:** 7,743 * `Number of instances:** 568,577 * `ClassLoader:** 38 (system class loader) * `DelegatingClassLoader:** 5 instances of `sun.reflect.DelegatingClassLoader` * `Method versions:** 256 * `VM operations:** 56

正文

https://www.jianshu.com/p/1ca44f94e42f

 

解决服务器进程退出问题(metaspace溢出)

  • 现象
    • 策划反应服务器进不去,远程看了一下进程消失了(crash)
    • 有时候也会出现能登录,但是无法执行操作(进程还在),无法被正常shutdown
    • 进程根目录下出现了java_pid16298.hprof文件,一看到就是内存溢出了
      • 觉得奇怪,应该不会是堆内存溢出,因为人数不多,初步怀疑是永久区溢出(Java8#Metaspace),下面果然得到验证
    • 因为启动参数加了-XX:+HeapDumpOnOutOfMemoryError
    • 还出现了hs_err_pid.log,即JVM致命错误日志
  • 日志查询(vim/grep/less/more)
    • vim std.log
      • esc /OutOfMemoryError ?OutOfMemoryError
      • n/N 下一个
    • less std.log | grep OutOfMemoryError
      • Caused by: java.lang.OutOfMemoryError: Metaspace
    • grep OutOfMemory std.log -A 50 -B 50 | less
      • /OutOfMemoryError n 下一个 q退出
    • less std.log
      • 出现冒号 /OutOfMemoryError 搜索 q退出 也可以?OutOfMemoryError
    • more std.log
      • /OutOfMemoryError 搜索 q退出 只能/
  • 从日志输出上看是: Metaspace内存溢出,我这边启动参数设置的大小是48M
    • -XX:MaxMetaspaceSize=48m
  • 从致命日志的输出看:也是jvm在Metaspace::allocate时出现了致命错误
    • Metaspace used 47519K, capacity 48950K, committed 49152K, reserved 1093632K...
    • 也能看到类似日志 发现确实Metaspace几乎已被占满
  • why?
    • Metaspace概念理解
      • JVM源码分析之Metaspace解密
      • java7和java8中部分原来在permgen的数据已经被转移到堆
      • 从JDK7开始永久代的移除工作,贮存在永久代的一部分数据已经转移到了Java Heap或者是Native Heap。但永久代仍然存在于JDK7,并没有完全的移除:符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java heap;类的静态变量(class statics)转移到了java heap
      • In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.
    • 哪些占用了空间(个人分析 主要是生成的类)
      • fastjson#asm(通过debug调试)
        • deserializer
          • ASMDeserializerFactory#createJavaBeanDeserializer
          • 当调用如JSON#parseObject(String text, Class<T> clazz),都会生成一个和clazz对应的如FastjsonASMDeserializer_53_xx类,用来进行反序列化
          • 目前用到的地方包括配置文件,数据表,玩家相关数据等
        • serializer
          • ASMSerializerFactory#createJavaBeanSerializer
          • 当调用如JSON.toJSONString(Object object),也会生成一个和object#clazz对应的如ASMSerializer_1_xx类,用来write/序列化
        • 二者加起来大约200个左右
      • lambda表达式内部类
        • 所有使用lambda表达式的地方都会生成一个如xxLambda1的类 大约150个左右
      • 其他如protobuf生成的类,大约200多个
      • 其他查看了一下$的内部类,也未发现有特殊的如生成的类
      • 搜索包含数字的类,因为通常动态生成的类似都有数字等
        • 发现了大量的sun.reflect.GeneratedMethodAccessor344...
        • 大概有350多个,同时发现了有同样数目的sun.reflect.DelegatingClassLoader(是只有一个类,只不过有对应数目的实例)..
        • 同样sun.reflect.GeneratedConstructorAccessor...
        • 分析-这个是是反射的优化,It can use a JNI accessor, or a Java bytecode accessor
          • JVM刚开始默认使用JNI的方式调用,当同一个类调用次数达到一定值后改为Java bytecode调用(会有一个新的classloader和一个clazz)
        • 关于反射调用方法的一个log
          • 网上有很多内容是关于因为这个的内存溢出问题,可以自行搜索查阅
        • 目前业务逻辑中频繁调用反射的地方
          • handler逻辑方法的反射执行
          • protobuf的反序列化
          • 其他三方库的反射等
    • 工具使用
      • jvisualvm#载入hprof#可安装插件
        • 从两个个hprof看,均是差不多载入了7700多个类的时候抛出了内存溢出错误
        • OQL控制台#右下方#保存的查询#PermGen分析#类加载器类型
        • 发现了一个有意思的:发现了大量的xxLambda143这样的类
          • Lambda表达式是要生成内部类的
          • 从输出看,Lambda表达式生成的内部类编号是从1开始,然后++
          • 目前看到的有151个Lambda内部类
        • 可直接在类信息下面搜索匹配
      • 使用mat
        • open heap dump
          • Size: 22.6 MB Classes: 7.5k Objects: 578k Class Loader: 357
        • JavaBasics#class loader explorer
          • 主要的几个classloader#sun.misc.Launch$ExtClassLoader#defined class 4312

          • com.alibaba.fastjson.util.ASMClassLoader(Deserializer_)#129
            > com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_53_xxConfig,这里需要排查为什么所有的Config对象都被生成了反序列化的内部类?还有其他如xx_RedisConfig等(了解fastjson#asm原理即可)

            com.alibaba.fastjson.serializer.ASMSerializer_70_xxConfig
            这里看了代码发现有一个xxMonsterConfig,这个是在序列化到redis的时候没有加SerializerFeature.IgnoreNonFieldGetter,序列化mongo的player已经统一加上了这个feature.

          • system class loader#2617

        • 这里解释一下
          • 为什么这里是ExtClassLoader加载了业务中的大部分类
          • 因为我这边启动是用-Djava.ext.dirs=lib,即ExtClassLoader加载的,而非AppClassLoader
      • 二者都可以使用OQL
        • OQL Syntax
        • SELECT DISTINCT OBJECTS classof(s) FROM "com.xx.*" s
          • 查询对象所属的类在com.xx包下
          • 大约有600多个
  • 总结和解决办法
    • 从上面分析看,确实应该是metaspace分配的空间过少 48M 准备调整为128M 再实际跑跑测试
    • Lambda表达式会生成内部类
    • 反射调用频繁JVM也会生成相应的类
  • 总结-2017.9.28
    • 因为进程crash的代价很大,虽然可以设置一个较大的metaspace,但是如果泄露了,进程直接crash,影响会非常大
      • 所以还是建议不设置这个参数,jvm自己调节。如果真出现了泄露,那么内存会一直疯长的
      • 而此时我们的运维监控系统是可以监听到的,可以即时报警,然后走正常的shutdown(shutdown之前可以jmap hprof),然后排查问题.
      • ps:OutOfMemory crash的时候会执行shutdownhook的,不过虽然如此但是进程突然crash,会影响到玩家体验,可能会造成流失.
  • std.log
Caused by: java.lang.OutOfMemoryError: Metaspace
        at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_40]
        at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_40]
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_40]
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_40]
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_40]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_40]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_40]
        at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_40]
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_40]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_40]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_40]
  • hs_err_pid.log
Stack: [0x00007f03927ff000,0x00007f0392900000],  sp=0x00007f03928fe340,  free space=1020k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xaaca9a]  VMError::report_and_die()+0x2ba
V  [libjvm.so+0x4f2de9]  report_fatal(char const*, int, char const*)+0x59
V  [libjvm.so+0xab3d6a]  VMThread::execute(VM_Operation*)+0x2ca
V  [libjvm.so+0x47ecf0]  CollectorPolicy::satisfy_failed_metadata_allocation(ClassLoaderData*, unsigned long, Metaspace::MetadataType)+0x150
V  [libjvm.so+0x8928c5]  Metaspace::allocate(ClassLoaderData*, unsigned long, bool, MetaspaceObj::Type, Thread*)+0x315
V  [libjvm.so+0x8a5a26]  MethodCounters::allocate(ClassLoaderData*, Thread*)+0x26
V  [libjvm.so+0x89d811]  Method::build_method_counters(Method*, Thread*)+0x71
V  [libjvm.so+0x8a01f0]  BreakpointInfo::set(Method*)+0x3a0
V  [libjvm.so+0x796cd6]  JvmtiBreakpoint::each_method_version_do(void (Method::*)(int))+0x56
V  [libjvm.so+0xab5ac5]  VM_Operation::evaluate()+0x55
V  [libjvm.so+0xab3e9a]  VMThread::evaluate_operation(VM_Operation*)+0xba
V  [libjvm.so+0xab421e]  VMThread::loop()+0x1ce
V  [libjvm.so+0xab4690]  VMThread::run()+0x70
V  [libjvm.so+0x910ee8]  java_start(Thread*)+0x108
  • java visualvm#载入信息
 生成的日期: Mon Sep 25 14:30:30 CST 2017
    文件: D:\xx\landon\task\2017.9\server_err\java_pid16298.hprof
    文件大小: 56.1 MB

    字节总数: 47,508,830
    类总数: 7,743
    实例总数: 568,577
    类加载器: 380
    垃圾回收根节点: 2,703
    等待结束的暂挂对象数: 0

    在出现 OutOfMemoryError 异常错误时进行了堆转储
    导致 OutOfMemoryError 异常错误的线程: queue-executor-handler-8
  • lambda$
com.xx.achilles.spurs.gs.model.combat.CombatService$$Lambda$143
com.xx.achilles.spurs.gs.model.raid.daily.DailyRaidManager$$Lambda$142
com.xx.achilles.spurs.gs.model.daily.DailyManager$$Lambda$141
...
  • mat#class loader explorer
Class Name                                           | Defined Classes | No. of Instances
------------------------------------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader @ 0x800230b0        |           4,312 |           93,289
<system class loader>                                |           2,617 |          484,122
com.alibaba.fastjson.util.ASMClassLoader @ 0x805fd848|             129 |              129
com.alibaba.fastjson.util.ASMClassLoader @ 0x805e2858|              73 |               73
------------------------------------------------------------------------------------------
...
  • sun.reflect.GeneratedMethodAccessor
Class Name                                               | Shallow Heap | Retained Heap
----------------------------------------------------------------------------------------
class sun.reflect.GeneratedMethodAccessor344 @ 0x80593e18|            0 |           568
class sun.reflect.GeneratedMethodAccessor343 @ 0x80593ee0|            0 |           568
class sun.reflect.GeneratedMethodAccessor342 @ 0x80593fa8|            0 |           568
class sun.reflect.GeneratedMethodAccessor341 @ 0x80594070|            0 |           568
class sun.reflect.GeneratedMethodAccessor340 @ 0x80594138|            0 |           568
class sun.reflect.GeneratedMethodAccessor339 @ 0x80594200|            0 |           568
class sun.reflect.GeneratedMethodAccessor338 @ 0x805942c8|            0 |           568
class sun.reflect.GeneratedMethodAccessor337 @ 0x80594390|            0 |           568
class sun.reflect.GeneratedMethodAccessor336 @ 0x80594458|            0 |           568
...
----------------------------------------------------------------------------------------

  • sun.reflect.DelegatingClassLoader
Class Name                                                     | Defined Classes | No. of Instances
----------------------------------------------------------------------------------------------------
sun.misc.Launcher$ExtClassLoader @ 0x800230b0                  |           4,312 |           93,289
<system class loader>                                          |           2,617 |          484,122
com.alibaba.fastjson.util.ASMClassLoader @ 0x805fd848          |             129 |              129
com.alibaba.fastjson.util.ASMClassLoader @ 0x805e2858          |              73 |               73
javax.management.remote.rmi.NoCallStackClassLoader @ 0x806fc4f8|               1 |                0
javax.management.remote.rmi.NoCallStackClassLoader @ 0x806fc5d0|               1 |                0
sun.reflect.DelegatingClassLoader @ 0x80593db8                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80593e80                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80593f48                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594010                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x805940d8                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x805941a0                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594268                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594330                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x805943f8                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x805944c0                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594588                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594650                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x805947c8                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594890                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594958                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594a20                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594ae8                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594bb0                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594c78                 |               1 |                1
sun.reflect.DelegatingClassLoader @ 0x80594d40                 |               1 |                1
----------------------------------------------------------------------------------------------------

与[转帖]JVM metaspace outofmemory相似的内容:

[转帖]JVM metaspace outofmemory

https://www.jianshu.com/p/1ca44f94e42f 解决服务器进程退出问题(metaspace溢出) 现象 策划反应服务器进不去,远程看了一下进程消失了(crash) 有时候也会出现能登录,但是无法执行操作(进程还在),无法被正常shutdown 进程根目录下出现了java

[转帖]【JVM】JVM源码分析之Metaspace解密

概述 metaspace,顾名思义,元数据空间,专门用来存元数据的,它是jdk8里特有的数据结构用来替代perm,这块空间很有自己的特点,前段时间公司这块的问题太多了,主要是因为升级了中间件所致,看到大家讨论来讨论去,看得出很多人对metaspace还是模棱两可,不是很了解它,因此我觉得有必要写篇文

[转帖]JVM调优汇总(JDK1.8)

JVM调优汇总 1、根据实际情况选择合适垃圾收集器 堆内存4G一下可以用parallel,4-8G可以用ParNew + CMS,8G以上可以用G1,几百级以上用ZGC。 2、jvm参数的初始值和最大值设置一样,避免扩容时消耗性能。 ‐Xms3072M ‐Xmx3072M ‐XX:Metaspace

[转帖]【JVM】关于 JVM,你需要掌握这些 | 一文彻底吃透 JVM 系列

【JVM】关于 JVM,你需要掌握这些 | 一文彻底吃透 JVM 系列 作者:冰河 2022-11-04 四川 本文字数:13519 字 阅读完需:约 44 分钟 写在前面 最近,一直有小伙伴让我整理下关于 JVM 的知识,经过十几天的收集与整理,初版算是整理出来了。希望对大家有所帮助。 JDK 是

[转帖]JVM内存非典型术语介绍(shallow/retained/rss/reserved/committed)

https://www.jianshu.com/p/871d6bb3a32d JVM内存非典型术语介绍(shallow/retained/rss/reserved/committed) 背景 ​ 在服务器性能优化内存这一项时,有一些现象很诡异。如top显示的RES很大,但是实际jvm堆内存占用很小,

[转帖]jvm crash when overwritten running jar

https://www.jianshu.com/p/bf0a051e4c63 现象 策划热更完配置表后 jvm直接就crash了(开发机linux) crash日志 日志分析 从crash日志看是reload配置表 使用Reflections扫描配置类 最终读取jar包 java.util.zip.

[转帖]jvm一般相关配置OutOfMemoryError关参数配置解释

一般运行java应用都会根据实际情况设置一些jvm相关运行参数 特别是有关内存和oom溢出等参数,方便后续问题定位和解决 如常用的以下配置 nohup java -Xms256m -Xmx24g -Xmn8g -verbose:gc -XX:+PrintGCDateStamps -XX:+Print

[转帖]JVM 中你不可不知的参数

https://zhuanlan.zhihu.com/p/91757020?utm_id=0 有的同学虽然写了一段时间 Java 了,但是对于 JVM 却不太关注。有的同学说,参数都是团队规定好的,部署的时候也不用我动手,关注它有什么用,而且,JVM 这东西,听上去就感觉很神秘很高深的样子,还是算了

[转帖]JVM参数之-XX:SurvivorRatio

https://www.cnblogs.com/hellxz/p/10841550.html 最近面试过程中遇到一些问JVM参数的,本着没用过去学习的办法看了些博客写得不准确,参考oracle的文档记录一下,争取每天记录一点知识点 -XX:SurvivorRatio=6 ,设置的是Eden区与每一个

[转帖]JVM 虚拟机(整体架构、类文件结构)我来了~~~

JVM 虚拟机(整体架构、类文件结构)我来了~~~ 虚拟机 1.1 发展历程 1.1.1 java 往事 ​ Java 诞生在一群懒惰、急躁而傲慢的程序天才之中。 ​ 1990 年 12 月,Sun 的工程师 Patrick Naughton 被当时糟糕的 Sun C++ 工具折磨的快疯了。他大声抱