如果在JVM 的配置中添加了DisableExplicitGC这个配置,但是同时应用中有用到了Direct ByteBuffer(例如用到了NIO框架mina),此时会由于内存问题导致OOM,之前有所了解,但是没有仔细看过,最近同事排查了一个这种问题,然后决定扫盲一下,期间重点参照撒迦(不得不佩服他在JVM上的权威)的这篇Topic(http://hllvm.group.iteye.com/group/topic/27945)。
(1)DisableExplicitGC这个配置的作用是啥?
-XX:+DisableExplicitGC标志自动将System.gc()调用转换成一个空操作,就是应用中调用System.gc()会变成一个空操作。最主要的原因是为了防止某些手贱的同学在代码里到处写System.gc()的调用而干扰了程序的正常运行吧。有些应用程序本来可能正常跑一天也不会出一次full GC,但就是因为有人在代码里调用了System.gc()而不得不间歇性被暂停。
(2)应用中调用System.gc()会有啥影响?
在Oracle/Sun JDK这个具体实现上,System.gc()的默认效果是引发一次stop-the-world的full GC,对整个GC堆做收集,对于应用的影响可想而知。
(3)DisableExplicitGC这个设置了会有啥坑?
其中一种情况是下述三个条件同时满足时会发生的:
1、应用本身在GC堆内的对象行为良好,正常情况下很久都不发生full GC;
2、应用大量使用了NIO的direct memory,经常、反复的申请DirectByteBuffer
3、使用了-XX:+DisableExplicitGC
此时有可能会抛出这个异常:java.lang.OutOfMemoryError: Direct buffer memory
(4)Direct ByteBuffer有啥值得注意的地方?
1、DirectByteBuffer没有finalizer,它的native memory的清理工作是通过sun.misc.Cleaner自动完成的。
2、sun.misc.Cleaner是一种基于PhantomReference的清理工具,比普通的finalizer轻量些。
做full GC的话会对old gen做reference processing,进而能触发Cleaner对已死的DirectByteBuffer对象做清理工作。
而如果很长一段时间里没做过GC或者只做了young GC的话则不会在old gen触发Cleaner的工作,
那么就可能让本来已经死了的、但已经晋升到old gen的DirectByteBuffer关联的native memory得不到及时释放。
3、为DirectByteBuffer分配空间过程中会显式调用System.gc(),以期通过full GC来强迫已经无用的DirectByteBuffer对象释放掉它们关联的native memory:
这几个实现特征使得Oracle/Sun JDK 6依赖于System.gc()触发GC来保证DirectByteMemory的清理工作能及时完成。
如果打开了-XX:+DisableExplicitGC,清理工作就可能得不到及时完成,于是就有机会见到direct memory的OOM。
(5)使用了Direct ByteBuffer应该咋处理?
如果你在使用Oracle/Sun JDK 6,应用里有任何地方用了direct memory,那么使用-XX:+DisableExplicitGC要小心。
如果用了该参数而且遇到direct memory的OOM,可以尝试去掉该参数看是否能避开这种OOM。
如果担心System.gc()调用造成full GC频繁,可以尝试下面提到 -XX:+ExplicitGCInvokesConcurrent 参数
( -XX:+ExplicitGCInvokesConcurrent System.gc()和应用程序并发执行,就是不stop-the-world)
-XX:+ExplicitGCInvokesConcurrent 或 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
这两个参数也是用来改变System.gc()的默认行为用的;不同的是这两个参数只能配合CMS使用(-XX:+UseConcMarkSweepGC),
而且System.gc()还是会触发GC的,只不过不是触发一个完全stop-the-world的full GC,而是一次并发GC周期。
CMS GC周期中也会做reference processing。
所以如果用这两个参数的其中一个,而不是用-XX:+DisableExplicitGC的话,就避开了由full GC带来的长GC pause,
同时NIO direct memory的OOM也不会那么容易发生。
(6)MaxDirectMemorySize 与 NIO direct memory 的默认上限
-XX:MaxDirectMemorySize 是用来配置NIO direct memory上限用的VM参数。
MaxDirectMemorySize没显式配置的时候,NIO direct memory可申请的空间的上限就是-Xmx减去一个survivor space的预留大小。
(7)HeapDump位置问题
-XX:+HeapDumpBeforeFullGC、-XX:+HeapDumpAfterFullGC、-XX:+HeapDumpOnOutOfMemoryError 这几个参数可以在不同条件下做出HPROF格式的heap dump。
如果不想费神去摸索到底各种环境被配置成什么样、“working directory”到底在哪里的话,就在VM启动参数里加上 -XX:HeapDumpPath=一个绝对路径 吧。这样,自动做出的heap dump就会被存到指定的目录里去。
分享到:
相关推荐
总的来说,ByteBuffer是Android开发中处理二进制数据的强大工具,熟练掌握其用法和优化策略,可以显著提高应用程序的性能。在处理大量数据交换、网络通信和图像处理等场景时,合理使用ByteBuffer至关重要。
在IT行业中,ByteBuffer是一个非常重要的概念,特别是在网络通信和数据处理领域。ByteBuffer是Java平台提供的一种高效的数据操作接口,它允许我们以字节为单位进行读写操作,这对于处理二进制数据尤其有用。在...
`ByteBuffer`会根据protobuf编码规则正确地读取和解析数据,包括`long`类型的字段。 在JavaScript中,`protobuf+long+bytebuffer`的组合使用可能涉及到以下步骤: 1. 定义protobuf消息格式(.proto文件)。 2. ...
本文主要关注的是Java NIO中的ByteBuffer,一个关键的数据容器,用于在通道(Channel)和缓冲区(Buffer)之间传输数据。ByteBuffer的用法是Java NIO学习中的核心内容。 首先,我们了解下ByteBuffer的基本概念。...
使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com
总的来说,Mina ByteBuffer是对Java NIO ByteBuffer的扩展和优化,它更加关注网络通信的性能和效率,提供了更适合网络服务开发的特性和功能。了解它们之间的差异对于高效利用Mina框架进行网络编程至关重要。通过阅读...
本教程重点讲解了`ByteBuffer`的几个关键属性:mark、position、limit和capacity,以及重要的操作方法如flip。这些概念和方法对于理解和使用Java NIO进行内存数据操作至关重要。 首先,`ByteBuffer`是`Buffer`接口...
在Android开发中,JNI(Java Native Interface)允许Java代码与其他编程语言进行交互,尤其是在需要高效内存操作...理解并熟练运用ByteBuffer的创建、操作和JNI交互机制,对于优化Android系统的低层功能和性能至关重要。
在IT领域,ByteBuffer通常被用作一个高效的缓冲区,它可以存储和操作字节序列,尤其在处理网络通信时,能有效地组织和传输数据。易语言作为中国本土的一种编程语言,以其独特的“中文编程”特性,降低了编程的门槛,...
主要解决从流中获取数据,缓存,拆解,可用于TCP粘包问题
ByteBuffer的设计灵感来源于Java语言中的同名类,它的主要功能是用于在网络协议的打包和解包过程中处理二进制数据。 ByteBuffer的核心概念是缓冲区,它允许开发者在内存中预先分配一大块空间,用于存储即将发送或者...
ios-byteBuffer [![CI状态]( Lee / ios-byteBuffer.svg?style = flat)]( Lee / ios-byteBuffer ) 用法 #分配 ByteBuffer *buffer = [ByteBuffer initWithOrder: ByteOrderLittleEndian]; #输入数据 - ( ...
java api之ByteBuffer基础、应用场景、实战讲解 文档中有丰富的例子代码实现
`dena-bytebuffer`库就是为了解决这个问题而生,它提供了一个高效的方式来存储和操作二进制数据。本文将详细探讨`dena-bytebuffer`的核心特性、使用方法以及其在实际项目中的应用。 一、`dena-bytebuffer`简介 `...
在Android和Java开发中,有时候我们需要处理C/C++风格的结构体数据,特别是在与底层通信或者跨平台项目中。在这种情况下,Javolution库提供了一个强大的解决方案,它允许我们在Java中方便地操作结构体数据。本文将...
jdk api-ServerSocketChannel、Selector、ByteBuffer结合实现网络报文间的通讯
protobuf.js 是一个JavaScript实现的Protocol Buffers库,它允许开发者在Web应用中...通过结合long.js和bytebuffer.js,protobuf.js克服了JavaScript在处理二进制数据和大整数时的局限性,确保了数据的正确解析和编码。
- **使用direct ByteBuffer**:对于大文件或频繁的数据传输,使用直接ByteBuffer(`ByteBuffer.allocateDirect(size)`)可以提高性能,因为它绕过了Java堆内存。 2. **正确处理SelectionKey** - **理解...