职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 473|回复: 6

也谈mina造成的OutofMemory

[复制链接]
秋秋 发表于 2011-8-25 10:17 | 显示全部楼层 |阅读模式
看到这篇帖子《使用Mina出现的JNI OutOfMemory的解决方法》说到的问题和我遇到的问题差不多。都是JNI向OS申请内存导致SWAP分区被写满,然后进不去OS,最后操作系统直接僵死了。
1:添加了 -XX:MaxDirectMemorySize=128m 参数后,发现后面依然会不使用物理内存,使用swap分区(vm.swappiness = 60),OS依然会很卡,内存使用不正常[没用物理内存]。
2:后来在 /etc/sysctl.conf 中加入 vm.swappiness = 0,执行 sysctl -p 来让OS尽量不使用swap分区,问题得到解决了。(我开发机上使用firefox,过几天也会使用swap分区,sudo swapoff -a 发现解决问题了。)
疑问:是什么参数导致java积极使用swap分区,没有使用物理内存?
jdk版本:java version "1.6.0_16"
OS:RedHat 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux


ksdal 发表于 2011-8-25 10:17 | 显示全部楼层
最近我也怀疑mina导致内存消耗增大问题。不知道有什么好的检测工具

钰云 发表于 2011-8-25 10:17 | 显示全部楼层
试试jprofile

钰云 发表于 2011-8-25 10:18 | 显示全部楼层
如果在linux 下的话,可以试试 jmap 看看里面的对象占用的比率

江波 发表于 2011-8-25 10:18 | 显示全部楼层
Direct memory的大小我不会查看,网上查找也没有找到合适的方法。
可以看看 @RednaxelaFX 的这个帖子:http://rednaxelafx.iteye.com/blog/1098791

yoyo 发表于 2011-8-25 10:18 | 显示全部楼层
这种问题还是MINA框架本身的局限性造成的。
MINA的读写都是非阻塞的,这种机制缺乏平衡系统压力的能力。
read过程是要把连接上的数据都读进内存,直到生成IOHandler处理的Message,如果IOHandler处理不过来的话(这种情况很常见,因为通常要访问数据库),会消耗大量的内存缓存这些Message。
write过程机制类似。IOSessioin.write也是非阻塞的,要发送的数据在发送到网络上之前都会保存在内存里,如果write速度超过网络速度,同样会有消耗大量内存的隐患。
如果你的应用可能会存在上述情况,建议使用其他的框架。


找不到我 发表于 2011-8-25 10:18 | 显示全部楼层
在mina的com.taobao.notify.remoting.core.buffer.IoBuffer中,
/** A flag indicating which type of buffer we are using : heap or direct */
    private static boolean useDirectBuffer = false;
/**
     * Returns the direct or heap buffer which is capable to store the
     * specified amount of bytes.
     *
     * @param capacity the capacity of the buffer
     *
     * @see #setUseDirectBuffer(boolean)
     */
    public static IoBuffer allocate(int capacity) {
        return allocate(capacity, useDirectBuffer);
    }

    /**
     * Returns the buffer which is capable of the specified size.
     *
     * @param capacity the capacity of the buffer
     * @param direct   <tt>true</tt> to get a direct buffer,
     *                 <tt>false</tt> to get a heap buffer.
     */
    public static IoBuffer allocate(int capacity, boolean direct) {
        if (capacity < 0) {
            throw new IllegalArgumentException("capacity: " + capacity);
        }

        return allocator.allocate(capacity, direct);
    }
而在相关的子类实现中,发现ByteArrayPool这个类中设置是传入的(我们没有用到),其他direct均为false。所以我们的内存应该是堆内存。
目前发现linux的virtaul memory的有些机器上会不断增加,相关的案例这里也有:
http://stackoverflow.com/questions/561245/virtual-memory-usage-from-java-under-linux-too-much-memory-used
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-9 09:53 , Processed in 0.126134 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表