【发布时间】: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 客户端试图解组来自服务器的响应的总是相同的堆栈跟踪。但如果它只是在这里失败,我们就不会,因为
- 代码中有一些奇怪的星座(Spring、cglib、xstream、Eureka,...)
- 这很可能发生在这里,因为发现客户端始终每 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