OutOfMemory错误但应用程序在java中继续

时间:2011-12-16 07:21:13

标签: java

我的应用程序中遇到OutOfMemory错误。但事情是我的应用程序继续运行虽然它已经抛出了OutOfMemeory。大约两分钟后,JVM已经退出并且pid文件被生成了抛出

java.lang.OutOfMemoryError: requested 746 bytes for jbyte in 
    /BUILD_AREA/jdk6_21/hotspot/src/share/vm/prims/jni.cpp. Out of swap space?.

1)即使抛出OutOfMemory错误,JVM仍然可以继续运行吗? 2)你还可以给我一些方向来进一步调查吗?

我正在粘贴日志中的摘录以便更好地理解。

1)有两个内存不足错误。一个在2011.12.09 16.04.09:446,另一个在2011.12.09 16.04.40:818

    2011.12.09 16.04.09:446 664849490 WARNING {HTTP@9800-168}RULEZ runtime exception [transcoding]
    java.lang.OutOfMemoryError
            at java.util.zip.Inflater.inflateBytes(Native Method)
            at java.util.zip.Inflater.inflate(Inflater.java:238)
            at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:135)
            at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:105)
            at java.util.jar.JarVerifier$VerifierStream.read(JarVerifier.java:428)
            at java.io.FilterInputStream.read(FilterInputStream.java:66)
            at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:75)
            at javax.mail.Session.loadProvidersFromStream(Session.java:932)
            at javax.mail.Session.access$000(Session.java:174)
            at javax.mail.Session$1.load(Session.java:870)
            at javax.mail.Session.loadResource(Session.java:1084)
            at javax.mail.Session.loadProviders(Session.java:889)
            at javax.mail.Session.<init>(Session.java:210)
            at javax.mail.Session.getInstance(Session.java:249)
    .
    .
    .[Application continues here]
    .
    .
    .
    2011.12.09 16.04.40:818 664882092 WARNING {HTTP@9800-168}RULEZ runtime exception [transcoding]
    java.lang.OutOfMemoryError
            at java.util.zip.Inflater.inflateBytes(Native Method)
            at java.util.zip.Inflater.inflate(Inflater.java:238)
            at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:135)
            at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:105)
            at java.util.jar.JarVerifier$VerifierStream.read(JarVerifier.java:428)
            at java.io.FilterInputStream.read(FilterInputStream.java:66)
            at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:75)
            at javax.mail.Session.loadProvidersFromStream(Session.java:932)
            at javax.mail.Session.access$000(Session.java:174)
            at javax.mail.Session$1.load(Session.java:870)
            at javax.mail.Session.loadResource(Session.java:1084)
            at javax.mail.Session.loadProviders(Session.java:889)
            at javax.mail.Session.<init>(Session.java:210)
            at javax.mail.Session.getInstance(Session.java:249)
    .
    .
    .
    .
    .

2)在12月9日16:07,JVM退出并创建了pid文件,如下所示。因此,OutOFMemory错误日志语句与jvm之间存在约2分钟的差距,以便退出并创建pid文件。

    $ls

    -rw-rw-r--   1 ins ins     156076 Dec  9 16:07 hs_err_pid29157.log
    -rw-------   1 ins ins 3055525888 Dec  9 16:07 core.29157


    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # java.lang.OutOfMemoryError: requested 746 bytes for jbyte in /BUILD_AREA/jdk6_21/hotspot/src/share/vm/prims/jni.cpp. Out of swap space?
    #
    #  Internal Error (allocation.inline.hpp:39), pid=21129, tid=667401120
    #  Error: jbyte in /BUILD_AREA/jdk6_21/hotspot/src/share/vm/prims/jni.cpp
    #
    # JRE version: 6.0_21-b06
    # Java VM: Java HotSpot(TM) Server VM (17.0-b16 mixed mode linux-x86 )
    # 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 (0x2f929000):  JavaThread "DRIVER:adapter:12:7" [_thread_in_vm, id=21834, stack(0x27c5b000,0x27c7c000)]

    Stack: [0x27c5b000,0x27c7c000],  sp=0x27c7a874,  free space=7e27c7c000k
    Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
    V  [libjvm.so+0x6a9262]
    V  [libjvm.so+0x2b277f]
    V  [libjvm.so+0x3c0b0f]
    C  [libocijdbc10.so+0x108ff]
    C  [libocijdbc10.so+0x11788]  Java_oracle_jdbc_driver_T2CConnection_lobGetLength+0x30
    J  oracle.jdbc.driver.T2CConnection.lobGetLength(J[BI)J

    Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
    J  oracle.jdbc.driver.T2CConnection.lobGetLength(J[BI)J
    J  oracle.jdbc.driver.T2CConnection.length(Loracle/sql/BLOB;)J
    J  com.fh.common.database.ReadConnectionImpl.getByteArray(Ljava/lang/String;Ljava/sql/ResultSet;I)[B
    J  com.fh.common.database.ReadConnectionWrapper.getByteArray(Ljava/lang/String;Ljava/sql/ResultSet;I)[B
    J  com.fh.mr.storage.MultiJDBCStorage.fillInitiator(Lcom/fh/common/database/ReadConnection;Ljava/lang/String;Ljava/sql/ResultSet;Lcom/fh/mr/router/TransactionResponder;)Lcom/fh/mr/router/TransactionInitiator;
    J  com.fh.mr.storage.MultiJDBCStorage.addInitiators(Lcom/fh/mr/router/TransactionResponder;Ljava/util/Collection;)V
    J  com.fh.mr.storage.CacheStorage.getResponderByTransactionID(Ljava/lang/String;)Lcom/fh/mr/router/TransactionResponder;
    j  com.fh.mr.router.RoutingEngine.getResponderByTransactionID(Ljava/lang/String;)Lcom/fh/mr/router/TransactionResponder;+5
    j  com.fh.mr.router.RoutingEngine.scheduleStatusResend(Ljava/lang/String;)Z+53
    j  com.fh.mr.router.RoutingEngine.scheduleResend(Lcom/fh/mr/message/Message;I)Z+68
    j  com.fh.mr.drivers.Driver.getMessage(Ljava/lang/Object;)Lcom/fh/mr/message/Message;+260
    J  com.fh.mr.drivers.Driver$QueueWorker.run()V
    j  com.fh.common.threadpool.ThreadControl.run()V+47
    j  com.fh.common.threadpool.ThreadPool$PoolThread.run()V+467
    v  ~StubRoutines::call_stub

Thanks,
Vijay

3 个答案:

答案 0 :(得分:3)

  

即使抛出OutOfMemory错误,JVM仍然可以继续运行吗?

不确定。可以捕获OutOfMemory错误,即使没有,它只会杀死当前线程。任何其他线程都可以继续运行。

  

你还可以给我一些方向来进一步调查吗?

根据stacktrace,你的程序在尝试打开一些jar文件时内存不足。然而,这并不一定是罪魁祸首(即占用过多记忆的任务)。您需要找出程序的哪些部分使用太多内存,然后以某种方式减少,或者为JVM分配更多内存。

您还应该注意内存泄漏,这些内容泄漏有时会发生在长时间运行的进程中,例如,当某些类重新加载时。如果您发现服务器进程的大小会随着时间的推移而逐渐增大,那么快速修复(比更改代码更容易)可能会在一段时间内重新启动它。

  

12月9日16:07,JVM退出并创建了pid文件,如下所示。

JVM因内部错误而崩溃。这不应该发生。但是,这很可能是由非常接近内存限制的两分钟操作引起的。在OutOfMemory错误之后,事情往往会破裂。你经常收到这份崩溃报告吗?

答案 1 :(得分:3)

  

1)即使抛出OutOfMemory错误,JVM仍然可以继续运行吗?

是的,经过时尚,取决于应用程序是什么以及它在做什么。

OOME的生命周期如下:

  • 应用程序尝试分配一些内存(一个新的对象或数组,一个新的线程堆栈,一个非堆缓冲区,etcera),并发现它不能。
  • (对于正常的堆分配)GC运行...并且无法回收足够的内存。
  • 在尝试分配内存的线程上抛出异常。

接下来会发生什么取决于应用程序如何处理异常。

  • 如果应用程序捕获它并挽救,那就是它。如果OOME被抛到“主”线程并且应用程序没有捕获它,那就相同了。
  • 如果应用程序捕获并尝试恢复,请参阅下文。
  • 如果应用程序没有捕获它,并且线程不是主线程,那么线程就会死掉,但应用程序会继续运行。

所以我们假设我们“继续前进”。它会起作用吗?答案是,这取决于。

  • 应用程序可以检测到线程已经死亡并重新创建替换吗?
  • 当OOME被抛出时,在做什么的应用程序是什么?
  • 是否正在更新关键数据结构?
  • 是否已展开堆栈导致有足够的对象符合垃圾回收条件以允许应用程序取得进展?
  • 应用程序是否会重复之前导致OOME的计算?

不幸的是,由于上述问题,应用程序通常无法继续。即使它可以继续下去,它也会很快再次失败。长时间运行的应用程序中OOME的根本原因通常是内存泄漏,最好的短期解决方法是重新启动JVM和应用程序。

  

2)你还可以给我一些方向来进一步调查吗?

如果你有内存泄漏,你可能无法通过查看OOME被抛出时发生的事情来推断出任何东西。失败的分配不太可能是问题的真正原因。

所以我的建议是通过检查应用程序的内存泄漏来启动

答案 2 :(得分:1)

正如其他人所说OutOfMemoryError是一个可以捕捉和处理的错误。

要进一步调查错误,您需要使用VisualVM

  • 查看实时应用程序的内存消耗
  • 浏览java生成的堆转储。

要生成堆转储,请使用-XX:+HeapDumpOnOutOfMemoryError参数启动应用程序,等待OutOfMemoryError,获取堆转储并将其提供给VisualVM。

搜索VisualVM和OutOfMemoryError将为您提供各种使用方案。