繁体   English   中英

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

[英]OutOfMemory error but application continues in 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退出并创建pid文件之间大约有2分钟的间隔。

    $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

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

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

您还可以给我一些指导,以便对此进行进一步调查吗?

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

您还应该注意长时间运行的进程有时会发生的内存泄漏,例如,某些类重新加载时。 如果发现服务器进程的大小随着时间的推移缓慢增长,则快速解决方案(比更改代码更容易)可能是不时地重新启动它。

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

JVM因内部错误而崩溃。 那不应该发生。 但是,这很可能是由于在非常接近内存限制的情况下运行了两分钟而引起的。 在发生OutOfMemory错误后,事情往往会中断。 您会更频繁地获得该崩溃报告吗?

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

是的,遵循某种方式,取决于应用程序是什么以及正在做什么。

OOME的生命周期如下:

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

接下来发生的情况取决于应用程序如何处理异常。

  • 如果应用程序将其捕获并解决,那就是。 如果将OOME抛出到“主”线程上,而应用程序没有捕获它,也是如此。
  • 如果应用程序将其捕获并尝试恢复,则...参见下文。
  • 如果应用程序未捕获到该线程,并且该线程不是主线程,则该线程死亡,但应用程序继续运行。

因此,假设我们正在“继续前进”。 能行吗 答案是,这取决于。

  • 应用程序可以检测到线程已死亡并重新创建替换线程吗?
  • 抛出OOME时正在执行的应用程序是什么?
  • 是在更新关键数据结构的过程中吗?
  • 展开堆栈是否已使足够的对象有资格进行垃圾回收以使应用程序取得进展?
  • 应用程序会重复生成OOME之前的计算吗?

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

2)您还可以给我一些指导,以便对此进行进一步调查吗?

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

因此,我的建议是检查应用程序内存泄漏开始。

正如其他人所说, OutOfMemoryError是可以捕获和处理的错误。

要进一步调查错误,您将需要使用VisualVM来执行以下操作:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM