문제

내 JVM이 충돌했고 hs_err 파일에 클래스를 로드하려고 시도하는 동안 충돌이 발생한 것으로 나타났습니다.특히 memcpy를 시도하는 동안([libc.so.6+0x6aa2c] memcpy+0x1c)..class 파일을 보고 어떤 클래스가 로드되고 있는지 확인할 수 있었습니다.

하지만 이 문제의 원인이 무엇인지, 원인에 대해 더 자세히 알아낼 수 있는 방법을 알려줄 수 있는 사람이 있나요?JVM에 메모리가 부족해도 오류가 발생하지 않습니다.어떤 통찰력이라도 대단히 감사하겠습니다.

내 hs_err 파일에서 발췌한 내용을 포함했습니다.

#
# 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
도움이 되었습니까?

해결책

우리는 비슷한 오류를 보았습니다. 우리의 현재 용의자는 프로세스가 실행되는 동안 (업그레이드 프로세스에 의해) 다시 작성된 JAR 파일입니다.

다른 팁

답 1이 맞습니다.java.util.zip.*의 구현에 결함이 있습니다.

Java 프로그램이 현재 "열려 있는"(ZipFile/JarFile 객체를 캐시한) zip/jar 파일을 교체하는 경우 원본 파일에서 읽은 캐시된 목차(TOC) 데이터를 사용하고 다음을 시도합니다. 이를 사용하여 대체된 파일의 데이터 압축을 풉니다.인플레이션 코드는 견고하지 않으며 잘못된 데이터가 표시되면 완전히 충돌합니다.

일반 유닉스 프로그램은 작업하는 동안 파일을 열어 둡니다.파일을 덮어쓰면 해당 파일을 사용하는 프로그램은 열린 파일 설명자 덕분에 열려 있던 원본에 계속 액세스할 수 있습니다.

OpenJDK의 java.util.zip.* 구현은 zip/jar 파일에 대해 파일 설명자를 열어두지 않도록 선택했습니다.그 이유 중 하나는 Java가 클래스 경로에 수백 개의 jar 파일과 함께 호출되는 경우가 많고 디자이너가 jar 파일에만 수백 개의 파일 설명자를 사용하여 프로그램 자체에 아무것도 남기지 않기를 원했기 때문일 수 있습니다.따라서 jar/zip 목차를 읽자마자 파일 설명자를 닫고 내용이 변경되면 원래 jar/zip 파일에 대한 액세스 권한을 영구적으로 잃게 됩니다.

어떤 이유로든 ZipFile은 zip/jar 파일이 변경되었음을 알려주지 않거나 알 수 없습니다.그렇다면 TOC를 다시 읽거나 불가능할 경우 일종의 오류가 발생할 수 있습니다.

게다가 TOC가 유효하더라도 잘못된 데이터로 인플레이터가 충돌하는 문제가 있습니다.ZIP 목차는 유효하지만 압축된 데이터 스트림이 의도적으로 잘못된 경우에는 어떻게 됩니까?

다음은 java.util.zip.*이 zip/jar 파일에 대해 파일 설명자를 열어 두지 않고 zip 파일이 변경되었음을 감지하지 않는다는 것을 증명하는 테스트 프로그램입니다.

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 */ }
        }
    }
}

이 프로그램을 실행하면 JVM 충돌이 발생합니다.

# 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

이에 대해 JVM에 대해 제출된 주요 버그는 다음과 같습니다. JDK-4425695:jar 파일을 업데이트하면 실행 중인 프로그램이 충돌함.

RFE 6929479:ZipFile에서 mmap 사용을 비활성화하려면 시스템 속성 sun.zip.disableMemoryMapping을 추가하세요. JDK7에서 시스템 속성을 구현합니다. sun.zip.disableMemoryMapping - 해결 방법으로 사용할 수 있습니다.

문제는 사용 중에 zip/jar 파일을 덮어 쓰고 있습니다. zip 파일 형식의 OpenJDK 코드는 기본 C 코드에 있습니다. 모든 항목 조회, 생성에는 비싼 JNI 호출의 여러 왕복이 필요합니다. 현재 기본 C 구현 코드는 MMAP를 사용하여 중앙 디렉토리 테이블에서 매핑을 사용합니다. 이는 기본 JAR 파일이 다른 ZipFile에서 여전히 사용하는 동안 새로운 내용으로 덮어 쓰기에 VM 충돌의 위험이 큰 경우가 있습니다. 사용 -dsun.zip.disablememorymapping = true 사용 문제가 해결됩니다.

JDK9이를위한 솔루션이있는 조기 액세스 빌드를 사용할 수 있습니다.

원래 문제를 확인하십시오 https://bugs.openjdk.java.net/browse/jdk-8142508 이는 9 초기 액세스 빌드 97에서 고정되었습니다.

평범한 ol 이외. JVM의 버그 (최신 버전으로 업그레이드하고 다시는 발생하지 않기를 바랍니다) 또는 일부 버기 3. JNI를 사용하는 파티 라이브러리에는 다른 두 가지 "흥미로운"것들이 있습니다.

  1. 하드웨어 실패 - 잘못된 RAM은 종종 부패한 파일 시스템이 플라킹 드라이브를 유발할 수있는 좋은 후보자입니다.

  2. Solaris에서 실행중인 경우 JVM이 JAR/Class 파일을 MMAPS에 해당하는 경우 JVM이 액세스 해야하는 경우에 클래스/JAR 파일이 잘린 경우 SIGBUS 오류를 얻을 수 있습니다.

정확히 같은 문제를 겪었 기 때문에 문제를 해결했는지 모르겠습니다. MMAP를 사용하여 64KB 파일을 메모리에 매핑하고 Memcpy를 사용하여 데이터를 버퍼로 복사합니다. JNI를 사용하거나 JNA를 사용할 때도 동일한 오류가 발생했습니다. 저는 몇 년 동안 경험이 풍부한 JNI 프로그래머이며 순수한 C 프로그램에서 동일한 논리를 정확하게 구현했습니다.

나는 그것이 sigs를 가두는 JDK의 버그라고 생각합니다. 그러나 나는 더 이상 그것을 파낼 시간이 없다. 지금은이 접근법을 포기하고 내가하고 싶은 일을하기 위해 다른 방법을 시도하기로 결정했습니다.

내가이 작업을 수행하는 이유에 관심이 있다면 JNI에서 스레드 안전 메모리 맵핑 파일을 구현하고 싶습니다. JDK의 구현에서 위치는 바이트 버퍼 (Filechannel에서 매핑 됨)의 글로벌 변수입니다. C ++ 프로그램에서 수행 한 여러 스레드에서 컨텐츠에 액세스하기 위해 하나의 MemoryMappedBuffer 인스턴스를 사용하고 싶습니다.

BTW, Mac OS X 10.10에서 JDK 7을 사용하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top