【问题标题】:What could cause the JVM to crash with SIGSEGV "ClassLoaderData::metaspace_non_null()"什么可能导致 JVM 因 SIGSEGV "ClassLoaderData::metaspace_non_null()" 而崩溃
【发布时间】:2016-06-22 08:30:33
【问题描述】:

我们在其中一台机器上运行了大约 40 个 JVM 进程(3.2.0-4-amd64 #1 SMP Debian 3.2.78-1 x86_64 GNU/Linux)。服务器有 32GB 内存,每个进程消耗 350 到 380MB 内存。每个进程都承载一个 Spring Boot 应用程序。有时,我们会看到其中一个 JVM 崩溃并出现以下错误。

#  SIGSEGV (0xb) at pc=0x00007f151891d5d0, pid=3049, tid=0x00007f14fa784700
# JRE version: Java(TM) SE Runtime Environment (8.0_92-b14) (build 1.8.0_92-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.92-b14 mixed mode linux-amd64 compressed oops)

V  [libjvm.so+0x4685d0]  ClassLoaderData::metaspace_non_null()+0xc0
V  [libjvm.so+0x8a17e0]  Metaspace::allocate(ClassLoaderData*, unsigned long, bool, MetaspaceObj::Type, Thread*)+0x170
V  [libjvm.so+0x8b4b46]  MethodCounters::allocate(ClassLoaderData*, Thread*)+0x26
V  [libjvm.so+0x8ac8b1]  Method::build_method_counters(Method*, Thread*)+0x71
V  [libjvm.so+0x681adb]  InterpreterRuntime::build_method_counters(JavaThread*, Method*)+0x2b
j  sun.reflect.GeneratedSerializationConstructorAccessor18988.newInstance([Ljava/lang/Object;)Ljava/lang/Object;+0
J 10626 C2 org.springframework.aop.framework.CglibAopProxy.getProxy(Ljava/lang/ClassLoader;)Ljava/lang/Object; (405 bytes) @ 0x00007f1509f7cca8 [0x00007f1509f77ec0+0x4de8]
J 11391 C2 org.springframework.cloud.netflix.eureka.DataCenterAwareMarshallingStrategy$PublishingApplicationsConverter.unmarshal(Lcom/thoughtworks/xstream/io/HierarchicalStreamReader;Lcom/thoughtworks/xstream/converters/UnmarshallingContext;)Ljava/lang/Object; (39 bytes) @ 0x00007f1509a8fee4 [0x00007f1509a8f4c0+0xa24]
J 11352 C2 org.springframework.cloud.netflix.eureka.DataCenterAwareMarshallingStrategy.unmarshal(Ljava/lang/Object;Lcom/thoughtworks/xstream/io/HierarchicalStreamReader;Lcom/thoughtworks/xstream/converters/DataHolder;Lcom/thoughtworks/xstream/converters/ConverterLookup;Lcom/thoughtworks/xstream/mapper/Mapper;)Ljava/lang/Object; (30 bytes) @ 0x00007f1509a344cc [0x00007f1509a33da0+0x72c]
J 12523 C2 com.sun.jersey.api.client.ClientResponse.getEntity(Ljava/lang/Class;Ljava/lang/reflect/Type;)Ljava/lang/Object; (246 bytes) @ 0x00007f150a3cbf94 [0x00007f150a3cb0e0+0xeb4]
J 11327 C2 com.netflix.discovery.DiscoveryClient.fetchRegistry(Z)Z (409 bytes) @ 0x00007f1509b4e7f0 [0x00007f1509b4e400+0x3f0]
J 11332 C2 com.netflix.discovery.DiscoveryClient$CacheRefreshThread.run()V (353 bytes) @ 0x00007f1509b49004 [0x00007f1509b48f60+0xa4]
...

这发生在不同服务的进程和不同的机器上,没有任何明显的原因。但是,我们看到的 Eureka 客户端试图解组来自服务器的响应的总是相同的堆栈跟踪。但如果它只是在这里失败,我们就不会,因为

  1. 代码中有一些奇怪的星座(Spring、cglib、xstream、Eureka,...)
  2. 这很可能发生在这里,因为发现客户端始终每 30 秒轮询一次服务器,并且很可能会在系统中遇到奇怪的情况(内存分配、碎片......)李>

虽然我们使用的是 Oracle JDK,但出于绝望,我检查了 the OpenJDK implementation 的这种方法,但没有立即知道可能出了什么问题。

我向 Oracle 提交了一份错误报告并与他们交换了几封电子邮件,但除了说没有此问题的复制者他们无法做任何事情之外,我没有收到他们的任何回复。

所以我的问题是——有什么可能的原因导致 JVM 中出现这样的错误?当我们之前在一个内存较少的系统上看到这个错误时,我们怀疑内存碎片太高,大约 2% 的可用内存,但我发现在内存消耗仅为 70% 左右的新系统上不太可能出现这种情况。除了 JVM 实现中的错误之外,还有什么其他解释该失败的原因?最重要的是 - 我们可以尝试如何可靠地重现此错误?

【问题讨论】:

  • 错误似乎来自反射期间的本机库(libjvm.so)。我在网上发现的大多数问题似乎都与 JDK 错误有关。这是有道理的,因为 SIGSEGV 应该是由错误的内存分配操作引起的。我们通常不会用 Java 去那么低。我建议您更新您的 oracle JDK,甚至使用 OpenJDK 部署您的一些实例以进行测试。祝你好运!

标签: java memory jvm spring-cloud segmentation-fault


【解决方案1】:

如果您提供完整的崩溃报告,那就太好了。 从这个小的堆栈跟踪中,我看到了一个有趣的部分

sun.reflect.GeneratedSerializationConstructorAccessor18988

这意味着您的应用程序中有 18988 个生成的访问器(我认为很多)。你可以在这里看到sun.reflect.MethodAccessorGenerator。 当你使用序列化或反射时,这可以生成新的类(sun.reflect.MethodAccessorGenerator#generate),然后每个类都会在 DelegatingClassLoder 中定义,每次都会创建(sun.reflect.ClassDefiner#defineClass)。

尝试提高通胀门槛

-Dsun.reflect.inflationThreshold = 一些很大的数字

它将推迟新访问器的生成。


您还可以通过 JMX 查看卸载了多少类(ClassLoading MBean), 你也可以运行

jcmd %pid% PerfCounter.print

并监控计数器 sun.gc.metaspace.capacity sun.gc.metaspace.maxCapacity sun.gc.metaspace.used

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2010-11-01
    相关资源
    最近更新 更多