问题
My JVM crashed the and the hs_err file showed that it crashed while attempting to load a class. Specifically while trying to memcpy ([libc.so.6+0x6aa2c] memcpy+0x1c). I looked at the .class file and was able to determine what class was being loaded.
But can any one tell me what could cause this or how i could determine more about the cause? If the JVM was out of memory wouldn't it throw an Error. Any insight is greatly appreciated.
I've included an excerpt from my hs_err file.
#
# An unexpected error has been detected by Java Runtime Environment:
#
# SIGBUS (0x7) at pc=0x005aba2c, pid=20841, tid=2427227056
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0_02-b05 mixed mode)
# Problematic frame:
# C [libc.so.6+0x6aa2c] memcpy+0x1c
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#
--------------- T H R E A D ---------------
Current thread (0x90d0dc00): JavaThread "ORDERHANDLER" [_thread_in_native, id=20881]
siginfo:si_signo=7, si_errno=0, si_code=2, si_addr=0x915e3000
Registers:
EAX=0x91218298, EBX=0xb7f2e71c, ECX=0x0000079b, EDX=0x915dfef2
ESP=0x90ac6a34, EBP=0x90ac6a60, ESI=0x915e2ffd, EDI=0x914f0a0d
EIP=0x005aba2c, CR2=0x915e3000, EFLAGS=0x00010206
Top of Stack: (sp=0x90ac6a34)
0x90ac6a34: b7f29d4b 914ed930 915dff20 00004f49
0x90ac6a44: 082e7bc4 00006f6f 00004243 00004f49
0x90ac6a54: b7f2e71c 080e3e54 00000000 90ac6a90
0x90ac6a64: b7f29fbb 080e3b00 080e3e54 00000000
0x90ac6a74: 00000000 90d0dc00 00000000 d68dd1b6
0x90ac6a84: b7f2e71c 90ac6ad8 90d0dcec 90ac6f00
0x90ac6a94: b7f21169 080e3b00 90ac6ad8 0000002b
0x90ac6aa4: 0000002b 90ac6ad8 00000008 00000000
Instructions: (pc=0x005aba2c)
0x005aba1c: 8b 74 24 08 fc d1 e9 73 01 a4 d1 e9 73 02 66 a5
0x005aba2c: f3 a5 89 c7 89 d6 8b 44 24 04 c3 90 90 90 90 90
Stack: [0x90a78000,0x90ac9000), sp=0x90ac6a34, free space=314k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libc.so.6+0x6aa2c] memcpy+0x1c
C [libzip.so+0xbfbb] ZIP_GetEntry+0x10b
C [libzip.so+0x3169] Java_java_util_zip_ZipFile_getEntry+0xc9
J java.util.zip.ZipFile.getEntry(JLjava/lang/String;Z)J
J java.util.zip.ZipFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
J java.util.jar.JarFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
J sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
J sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
J java.net.URLClassLoader$1.run()Ljava/lang/Object;
v ~StubRoutines::call_stub
V [libjvm.so+0x20bbbd]
V [libjvm.so+0x30a6b8]
V [libjvm.so+0x20ba50]
V [libjvm.so+0x26190b]
C [libjava.so+0xaa5c] Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2+0x3
c
J java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;
J java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;
J java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
J sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
j java.lang.ClassLoader.loadClassInternal(Ljava/lang/String;)Ljava/lang/Class;+2
v ~StubRoutines::call_stub
V [libjvm.so+0x20bbbd]
V [libjvm.so+0x30a6b8]
V [libjvm.so+0x20b6e1]
V [libjvm.so+0x20b7ca]
V [libjvm.so+0x367621]
V [libjvm.so+0x3662a5]
V [libjvm.so+0x365357]
V [libjvm.so+0x365112]
V [libjvm.so+0x1adb03]
V [libjvm.so+0x1aeb32]
V [libjvm.so+0x2d75cb]
V [libjvm.so+0x2d8a94]
V [libjvm.so+0x2d8a17]
V [libjvm.so+0x1fe7f8]
j com.aqua.foms.book.OrderHandler.handleNewOrder(Lcom/aqua/NmsApi/OrderMap;Lcom/aqua/api/AtsMessage;)V+221
j com.aqua.foms.book.FMSNewOrderTask.execute()V+12
j com.aqua.api.EEDefaultWorkerThread.run()V+96
v ~StubRoutines::call_stub
V [libjvm.so+0x20bbbd]
V [libjvm.so+0x30a6b8]
V [libjvm.so+0x20b4d0]
V [libjvm.so+0x20b55d]
V [libjvm.so+0x27b795]
V [libjvm.so+0x383ef0]
V [libjvm.so+0x30b5a9]
C [libpthread.so.0+0x5371]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J java.util.zip.ZipFile.getEntry(JLjava/lang/String;Z)J
J java.util.zip.ZipFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
J java.util.jar.JarFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
J sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
J sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;
J java.net.URLClassLoader$1.run()Ljava/lang/Object;
v ~StubRoutines::call_stub
J java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;
J java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;
J java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
J sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
j java.lang.ClassLoader.loadClassInternal(Ljava/lang/String;)Ljava/lang/Class;+2
v ~StubRoutines::call_stub
j com.aqua.foms.book.OrderHandler.handleNewOrder(Lcom/aqua/NmsApi/OrderMap;Lcom/aqua/api/AtsMessage;)V+221
j com.aqua.foms.book.FMSNewOrderTask.execute()V+12
j com.aqua.api.EEDefaultWorkerThread.run()V+96
v ~StubRoutines::call_stub
--------------- P R O C E S S ---------------
Java Threads: ( => current thread )
0x080c9c00 JavaThread "pool-1-thread-3" [_thread_blocked, id=18725]
0x0824f800 JavaThread "pool-1-thread-2" [_thread_blocked, id=13693]
0x91217c00 JavaThread "AquaSchedulerService_7" daemon [_thread_blocked, id=23675]
0x91215c00 JavaThread "AquaSchedulerService_6" daemon [_thread_blocked, id=23001]
0x91215400 JavaThread "AquaSchedulerService_5" daemon [_thread_blocked, id=22759]
0x91213400 JavaThread "AquaSchedulerService_4" daemon [_thread_blocked, id=22410]
0x91212c00 JavaThread "AquaSchedulerService_3" daemon [_thread_blocked, id=22262]
0x08316400 JavaThread "pool-1-thread-1" [_thread_blocked, id=22260]
0x0827d000 JavaThread "JmsConn_1_sender_0" daemon [_thread_blocked, id=21196]
0x90d0cc00 JavaThread "Timer-0" [_thread_blocked, id=20882]
=>0x90d0dc00 JavaThread "ORDERHANDLER" [_thread_in_native, id=20881]
0x90d0d400 JavaThread "TradeInviteMonitor" [_thread_blocked, id=20880]
0x90d09c00 JavaThread "ROUTERT" [_thread_blocked, id=20878]
0x90d09000 JavaThread "TIBCO EMS Session Dispatcher (33197)" [_thread_blocked, id=20877]
0x08310800 JavaThread "DORDERHANDLER" [_thread_blocked, id=20874]
0x90d01c00 JavaThread "Thread-12" daemon [_thread_blocked, id=20873]
0x90d03000 JavaThread "Thread-11" daemon [_thread_in_native, id=20872]
0x082e1c00 JavaThread "DELAYEDORDMON" [_thread_blocked, id=20871]
0x082e8000 JavaThread "DBUPD" [_thread_blocked, id=20870]
0x914e5000 JavaThread "pool-2-thread-1" [_thread_blocked, id=20869]
0x914e3c00 JavaThread "StatusStatsEventDispatcherThread" [_thread_blocked, id=20868]
0x082c8400 JavaThread "TimerQueue" daemon [_thread_blocked, id=20866]
0x082ca000 JavaThread "MDATATHREAD" [_thread_blocked, id=20865]
0x082c9400 JavaThread "AquaSchedulerService_2" daemon [_thread_blocked, id=20864]
0x9122b000 JavaThread "DestroyJavaVM" [_thread_blocked, id=20843]
0x91200800 JavaThread "FirmMatchingServer" [_thread_blocked, id=20863]
0x914de800 JavaThread "TIBCO EMS TCPLink Reader (32084)" daemon [_thread_in_native, id=20861]
0x9122a400 JavaThread "TIBCO EMS Connections Pinger" daemon [_thread_blocked, id=20859]
0x914d4000 JavaThread "WDISTQ" [_thread_blocked, id=20858]
0x9121f400 JavaThread "JmsConn_1_connector_0" daemon [_thread_blocked, id=20857]
0x914d8000 JavaThread "JmsConn_1_receiver_0" daemon [_thread_blocked, id=20856]
0x9149ac00 JavaThread "AquaSchedulerService_1" daemon [_thread_blocked, id=20855]
0x9149b400 JavaThread "AquaSchedulerService_0" daemon [_thread_blocked, id=20854]
0x9142a000 JavaThread "MySQL Statement Cancellation Timer" daemon [_thread_blocked, id=20852]
0x91425c00 JavaThread "Dispatcher-Thread-0" daemon [_thread_blocked, id=20851]
0x080bf800 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=20849]
0x080bdc00 JavaThread "CompilerThread0" daemon [_thread_blocked, id=20848]
0x080bcc00 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=20847]
0x080a9800 JavaThread "Finalizer" daemon [_thread_blocked, id=20846]
0x080a8800 JavaThread "Reference Handler" daemon [_thread_blocked, id=20845]
Other Threads:
0x080a5400 VMThread [id=20844]
0x080c1000 WatcherThread [id=20850]
VM state:not at safepoint (normal execution)
VM Mutex/Monitor currently owned by a thread: None
回答1:
we've seen similar errors. our current suspect is jar files which are re-written (by an upgrade process) while the process is running.
回答2:
Answer 1 is correct. The implementation of java.util.zip.* is at fault.
If you replace a zip/jar file that a Java program currently has "open" (has cached the ZipFile/JarFile object), it will use cached table-of-contents (TOC) data it read from the original file, and will try and use that to unpack data in the replaced file. The inflation code is not robust and will outright crash when presented with bad data.
Normal unix programs keep files open while they're working with them. If you overwrite the file, the program using it still has access to the original that it opened, by virtue of the open file descriptor.
OpenJDK's java.util.zip.* implementation chose not to keep file descriptors open for zip/jar files. One reason for this could be that Java is often invoked with hundreds of jar files in the class path, and the designers didn't want to use up hundreds of file descriptors on the jar files alone, leaving none left for the program itself. So they close file descriptors as soon as they've read the jar/zip table of contents, and permanently lose access to the original jar/zip file, should its contents change.
For whatever reason, ZipFile does not or cannot tell a zip/jar file has changed. If it did, it could re-read the TOC or throw some kind of Error if that's not possible.
Furthermore, even if the TOC remained valid, it's a problem that the inflater crashes on faulty data. What if the ZIP table-of-contents was valid but the deflated data stream was deliberately wrong?
Here's a test program that proves java.util.zip.* doesn't keep file descriptors open for zip/jar files and doesn't detect that the zip file has changed.
import java.util.zip.*;
import java.io.*;
public class ZipCrashTest {
public static void main(String args[]) throws Exception {
// create some test data
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) sb.append("Hello, World\n");
final byte[] data = sb.toString().getBytes();
// create a zip file
try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream("test1.zip"))) {
zo.putNextEntry(new ZipEntry("world.txt")); zo.write(data, 0, data.length); zo.closeEntry();
zo.putNextEntry(new ZipEntry("hello.txt")); zo.write(data, 0, data.length); zo.closeEntry();
}
// create a second valid zip file, but with different contents
try (ZipOutputStream zo = new ZipOutputStream(new FileOutputStream("test2.zip"))) {
zo.putNextEntry(new ZipEntry("hello.txt")); zo.write(data, 0, data.length); zo.closeEntry();
zo.putNextEntry(new ZipEntry("world.txt")); zo.write(data, 0, data.length); zo.closeEntry();
}
// open the zip file
final ZipFile zf = new ZipFile("test1.zip");
// read the first file from it
try (InputStream is = zf.getInputStream(zf.getEntry("hello.txt"))) {
while (is.read() != -1) { /* do nothing with the data */ }
}
// replace the contents of test1.zip with the different-but-still-valid test2.zip
Runtime.getRuntime().exec("cp test2.zip test1.zip");
// read another entry from test1.zip: it does not detect that the file has changed.
// the program will crash here
try (InputStream is = zf.getInputStream(zf.getEntry("world.txt"))) {
while (is.read() != -1) { /* do nothing */ }
}
}
}
Running this program should give you a JVM crash:
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGBUS (0x7) at pc=0x00007fb0fbbeef72, pid=4140, tid=140398238095104
...
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libzip.so+0x4f72] Java_java_util_zip_ZipFile_getZipMessage+0x1132
C [libzip.so+0x5d7f] ZIP_GetEntry+0xcf
C [libzip.so+0x3904] Java_java_util_zip_ZipFile_getEntry+0xb4
j java.util.zip.ZipFile.getEntry(J[BZ)J+0
j java.util.zip.ZipFile.getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;+38
j ZipCrashTest.main([Ljava/lang/String;)V+476
The main bug filed against the JVM for this is JDK-4425695 : Updating jar files crashes running programs.
RFE 6929479: Add a system property sun.zip.disableMemoryMapping to disable mmap use in ZipFile implements a system property in JDK7 - sun.zip.disableMemoryMapping
- which you could use as a workaround.
回答3:
Issue is zip/JAR file is being overwritten while in use. OpenJDK code for ZIP file format is in native C code any entry lookup, creation requires multiple round-trip of expensive jni invocations. The current native C implementation code uses mmap to map in the central directory table which is a big risk of vm crash when the underlying jar file gets overwritten with new contents while it is still being used by other ZipFile, that is what is happening. Using - Dsun.zip.disableMemoryMapping=true will solve the problem,
JDK9 early access builds are available that has solution for this.
Check the original issue https://bugs.openjdk.java.net/browse/JDK-8142508 that has been fixed in 9 early access build 97.
回答4:
Other than a plain ol. bug in the JVM(upgrade to the latest version and hope it doesn't happen again) - or some buggy 3. party libraries using JNI, there's 2 other "interesting" things that could cause this.
Hardware failure - bad RAM is often a good candidate ot a corrupted filesystem could cause of a flaky drive could be a culprit too.
If you're running on Solaris, you can get SIGBUS errors if somehow the class/jar file was truncated just when the JVM needs to access it in the cases the JVM mmaps the jar/class file.
回答5:
I don't know if you have solved the problem because I encountered exactly the same problem. I only use mmap to map a 64KB file into a memory and use memcpy to copy data to/from the buffer. The same error occurred either when I use JNI or when I use JNA. I'm an experienced JNI programmer for years and I'm exactly implemented the same logic in a pure C program which works pretty well.
I assume it's a JDK's bug which trap some SIGs. But I really don't have time to dig it any more. For now I decided to abandon this approach and try other way to do something I wanna do.
If you're interested in why I'm doing this, I just wanna implement a thread safe memory mapped file in JNI. Because in JDK's implementation, the position is a global variable in ByteBuffer(which is mapped from FileChannel). I just wanna use one MemoryMappedBuffer instance to access the content in multiple threads which I've done in a C++ program.
BTW, I'm using JDK 7 in Mac OS X 10.10.
来源:https://stackoverflow.com/questions/1313071/jvm-crash-while-memcpy-during-class-load