Oracle JVM加载类时出现的一个异常退出问题

1,529 views

最近线上环境的一个组件出现了异常退出的现象。接到报障后,为避免业务中断时间过长,影响用户工作,组里同事对事故现场作了简单的调查,收集了必要的数据后,重启了组件,恢复了业务。
依据事故现场收集到的信息(主要是JVM生成的hs_err_pid.log文件),可以确认组件异常退出时,对应的JVM正在加载类。在网上搜索,可以找到如下文章。但现场收集到的信息比较少,恢复业务时操作比较匆忙,没有收集更多的信息,所以本问题的定位无法继续,只能到此为止。
但收集到的文章比较有意思,值得一读。

  • JDK-7129299 : JVM crash issue related to jar files

    This may be another cases where a zip/JAR file is overwritten while it is being used. In JDK7 the property sun.zip.disableMemoryMapping can be used to disable the mmapping of the central directory to avoid this when there is stepping on toes.

  • Java SE 6 Advanced and Java SE 6 Support (formerly known as Java SE for Business 6) Release Notes

    Changes in 6u21-rev-b09
    Disabling mmap Usage (on Solaris or Linux)
    This release includes a new system property, sun.zip.disableMemoryMapping, which allows the user to disable the mmap usage in Sun’s java.util.zip.Zipfile implementation (on Solaris and Linux platforms). Solaris or Linux applications that use java.util.zip.ZipFile may experience a SIGBUS VM crash if the application accidentally overwrites any zip or jar files that are still being used by the same Java runtime.
    在Solaris和Linux平台下,Sun(Oracle)发布的JDK中java.util.zip.Zipfile类的实现里,有代码使用了操作系统提供的mmap特性。在某些特殊的场景(比如JVM已加载的jar或者zip被外部修改后,JVM再次读取该文件的内容)下,该特性会导致JVM收到SIGBUS,进而导致JVM异常退出。
    Although this is a programming error of the offending application, this system property provides a solution to avoid the VM crash. With the property set to true (-Dsun.zip.disableMemoryMapping=true, or simply -Dsun.zip.disableMemoryMapping) the Sun JDK/JRE runtime disables the mmap usage and the VM crash that might otherwise occur by overwriting the jar or zip file can be avoided.
    类似的现象并非由JVM自身的Bug导致,但Oracle JVM开发团队仍然提供了规避方案(从其它文章看,JVM的开发团队其实并不是非常情愿)。启动应用时,为JVM传入参数-Dsun.zip.disableMemoryMapping=true或者-Dsun.zip.disableMemoryMapping,可以避免jar或者zip文件操作时引发的JVM异常退出现象。

  • [Bug 190481] New: Consider using -Dsun.zip.disableMemoryMapping=true

    See Java bugs #4425695, #6929479. As of JDK 6u21 or 7, a system property can be set to prevent JVM crashes when overwriting an open JAR. (Only applies to Unix, since on Windows you could not open the JAR for writing to begin with.) This may be helpful to avoid crashes caused by buggy Ant scripts, etc. But needs to be checked to see if performance degrades as a result.

  • JVM crashes due to corrupted JAR file

    The reason why JAR files cannot be modified underneath the JVM is because the JVM caches each JAR file’s central directory structure (using mmap) for performance reasons. The central directory is the part of the JAR file that describes its contents – i.e. entry locations, sizes and so on. Caching it in memory means that the JVM does not have to read it from the disk every time an entry in that JAR file needs to be accessed.
    默认情况下,JVM从jar加载类时,会使用平台的mmap特性将jar文件的结构信息缓存到内存中,以此方法避免对jar文件结构进行反复读取,借以提高工作效率。
    If the JAR file is modified after this region has been cached, then the JVM’s version of the central directory will no longer be an accurate description of the JAR file as it exists on disk and the end result is a SIGBUS or SIGSEGV when the JVM attempts to load an entry from the modified JAR file (usually during class loading).
    Note: This has been a well known limitation of the HotSpot JVM for a long time but Oracle did recently introduce an option to work around the issue. From 1.6.0_23 onwards, the following option can be added to the command line to completely disable memory mapping for ZIP/JAR files:
    -Dsun.zip.disableMemoryMapping=true
    Enabling this option will impact performance because the VM will have to conduct some additional disk IO every time it reads an entry from a JAR file (to interrogate the central directory structure).
    启用本选项后,JVM加载类时需要花费时间直接从硬盘上的jar文件中加载所需的数据;相比于启用该选项前,引发了额外的硬盘IO操作,因而对JVM、应用的性能产生一些影响。
    As a result, you should verify whether any jar files were modified some time prior to the crashes starting, while the JVM was still running.
    遇到类似前述的异常退出现象后,开发人员需要确认在JVM正常启动后、到异常退出前,是否发生过jar文件被修改的现象。

  • weblogic jvm -Dsun.zip.disableMemoryMapping=true

    There are three possible scenarios here:
    三种场景
    1. While a class is in use it is dynamically reloaded from a jar file.
    类已加载,但重新被ClassLoader加载时。
    2. While a jar file is being accessed by the class loader, the jar file is being modified.
    类加载器正在访问某jar文件时,该jar被外部修改了。
    3. A Jarfile which was bigger than 4GB was accessed (applies to Java 6 and earlier only).
    对于1.6及以前版本的JDK,待访问的jar文件长度超出4GB。

    这篇文章附有完全的异常信息,可以和官方提供的异常信息对照着分析。



若非注明,均为原创,欢迎转载,转载请注明来源:Oracle JVM加载类时出现的一个异常退出问题

关于 JackieAtHome

基层程序员,八年之后重新启航

此条目发表在 JVM 分类目录,贴了 , 标签。将固定链接加入收藏夹。