固定对象溢出异常?

2022-09-03 16:01:43

不过,在日志中获取以下错误。我没有看到它对我的应用程序的任何可见影响,例如对UI或性能的影响。使用weblogic Jrockit JVM。

Caused by: java.lang.InternalError: pinned object overflow!
    at java.util.zip.Inflater.inflateBytes(Inflater.java:381) ~[na:1.6.0_31]
    at java.util.zip.Inflater.inflate(Inflater.java:231) ~[na:1.6.0_31]
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:135) ~[na:1.6.0_31]
    at java.io.FilterInputStream.read(FilterInputStream.java:116) ~[na:1.6.0_31]
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264) ~[na:1.6.0_31]

在网络上,我没有找到任何特定于异常的东西。对我来说,这看起来不像编程问题,而是与weblogic或jrockit相关的问题?pinned object overflow

任何指针,我该如何摆脱这个?


答案 1

固定对象?:

让我们先了解一下 Pinning Object.基本上,Pinning 是我们临时在堆上标记一个对象,这样垃圾回收器就不会尝试移动对象,直到我们删除标签。通常,如果对象正在升级(即从年轻空间移动到旧空间)或作为压缩(碎片整理)的一部分,则可能会从一个地址移动到另一个地址。但是,如果对象被固定,则 GC 不会尝试移动它,直到它被取消固定。

那么,我们为什么要固定一个对象呢

固定对于简单的性能优化非常重要。在 I/O 操作期间固定缓冲区(字节数组)允许我们将其地址直接传递给操作系统。由于缓冲区已固定,因此我们不必担心垃圾回收器会在 I/O 操作完成之前尝试将其移动到其他地址。

如果我们无法固定缓冲区,则需要分配额外的本机(堆外)内存以传递给操作系统的本机 I/O 调用,并在堆上和堆外缓冲区之间复制数据。

因此,通过将缓冲区固定到堆上的常量地址,我们避免了既需要执行冗余本机内存分配又需要复制。

何时可能发生固定对象溢出?

此情况可能发生在 JNI 调用期间或 I/O 调用中的异常处理错误期间。要找出真实的事实,我们必须分析线程转储以找出有多少线程被阻塞,即。卡住了。

故障 排除:

那么,当您的线程似乎卡在对readBytesPinned或d writeBytesPinned的调用中时,您应该怎么做?这完全取决于应用程序尝试从何处读取数据或将数据写入位置。

让我们看一个真实的例子,一个线程卡住做阻塞读取:

   "ExecuteThread: '2' for queue: 'weblogic.kernel.Default'" id=20 idx=0x2e tid=16946 prio=5 alive, in native, daemon
        at jrockit/net/SocketNativeIO.readBytesPinned(I[BIII)I(Native Method)
        at jrockit/net/SocketNativeIO.socketRead(Ljava/io/FileDescriptor;[BIII)I(Unknown Source)[inlined]
        at java/net/SocketInputStream.socketRead0(Ljava/io/FileDescriptor;[BIII)I(Unknown Source)[inlined]
        at java/net/SocketInputStream.read([BII)I(SocketInputStream.java:113)[optimized]
        at oracle/net/ns/Packet.receive()V(Unknown Source)[inlined]
        at oracle/net/ns/DataPacket.receive()V(Unknown Source)[optimized]
        at oracle/net/ns/NetInputStream.getNextPacket()V(Unknown Source)[optimized]
        at oracle/net/ns/NetInputStream.read([BII)I(Unknown Source)[inlined]
        at oracle/net/ns/NetInputStream.read([B)I(Unknown Source)[inlined]
        at oracle/net/ns/NetInputStream.read()I(Unknown Source)[optimized]
        at oracle/jdbc/driver/T4CMAREngine.unmarshalUB1()S(T4CMAREngine.java:1099)[optimized]
<rest of stack omited> 

在上面的例子中,你可以从堆栈跟踪中看出 JDBC(数据库)驱动程序正在从网络套接字执行阻塞读取。因此,典型的下一步是查看是否存在预期数据可能延迟(甚至根本没有到达)的原因。例如,我们正在与之交谈的数据库服务器可能挂起,可能存在延迟(甚至丢弃)数据库响应的网络问题,或者可能存在某种协议不匹配,双方都认为轮到对方说话了。分析双方的日志文件可能会提供有关所发生情况的线索。如果问题是可重现的,那么收集网络跟踪并使用WireShark等工具对其进行分析也可能很有用。

解决 方案:

找到正确的理由后,您可以编写适当的异常处理,当然,当我们完成它时,请关闭FileInputStream,以避免不必要的溢出。

参考资料:thread_stuck_at_readbytespinned_writebytespinned


答案 2