操作系统:Linux
java版本:sun java 1.4.2
内存:2G描述:相同的配置,一台服务器上程序(Socket程序)一切正常;另外一台,过不了多久,系统就抛出OOM。
基本可以确认,程序是在操作Hashtable的时候,出现OOM的。控制台verbosegc 日志如下:
[GC 1152K->648K(1984K), 0.0005830 secs]
[GC 1160K->648K(1984K), 0.0004750 secs]
[GC 1160K->673K(1984K), 0.0005340 secs]
[GC 1185K->655K(1984K), 0.0006800 secs]
[GC 769K->651K(1984K), 0.0005900 secs]
[Full GC[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor3]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor4]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor2]
 651K->432K(1984K), 0.0238370 secs]
[Full GC 432K->362K(61120K), 0.0306660 secs]
java.lang.OutOfMemoryError程序日志:
2005/12/11 22:38:32 [DEBUG] - add Stand Remote One:136345@aa
2005/12/11 22:38:32 [DEBUG] - add Stand Remote One:1378@aa也有remove之后,出现OOM的,控制台日志类似。另外一台几乎相同配置的服务器上,日志稍有不同,程序也没有出现OOM。
相关 verbosegc 日志如下:
[GC 1856K->1341K(1984K), 0.0014380 secs]
[GC 1844K->1368K(1984K), 0.0006190 secs]
[GC 1865K->1395K(1984K), 0.0004970 secs]
[GC 1878K->1421K(1984K), 0.0004200 secs]
[GC 1909K->1448K(1984K), 0.0003740 secs]
[GC 1939K->1475K(2112K), 0.0007810 secs]
[Full GC 1475K->902K(2112K), 0.0984150 secs]
[GC 1406K->972K(2112K), 0.0006510 secs]
[GC 1473K->1017K(2112K), 0.0008270 secs]
[GC 1521K->1008K(2112K), 0.0004760 secs]
[GC 1518K->973K(2112K), 0.0008050 secs]
[GC 1476K->1018K(2112K), 0.0006390 secs]
[GC 1528K->974K(2112K), 0.0020650 secs]
[GC 1485K->1019K(2112K), 0.0005660 secs]
[GC 1518K->1028K(2112K), 0.0004710 secs]
[GC 1538K->1008K(2112K), 0.0005270 secs]
[GC 1513K->1036K(2112K), 0.0004520 secs]
[GC 1547K->1044K(2112K), 0.0004310 secs]
[GC 2028K->1518K(2112K), 0.0004000 secs]
[GC 1998K->1552K(2112K), 0.0004290 secs]
[GC 2035K->1586K(2240K), 0.0022100 secs]
[Full GC 1586K->898K(2240K), 0.0402230 secs]
[GC 1399K->981K(2112K), 0.0003080 secs]
[GC 1467K->1048K(2112K), 0.0003050 secs]
[GC 1537K->1083K(2112K), 0.0004330 secs]
[GC 1589K->1083K(2112K), 0.0002310 secs]
[GC 1575K->1118K(2112K), 0.0003160 secs]
[GC 1612K->1152K(2112K), 0.0002430 secs](jvm的heap似乎可以自动调节?)相关源代码:    public void addLocalOne( User xu )
    {
        String tel = xu.getTel();
        htLocalUser.put( tel, xu );
        LoggerUtils.debug( "add Stand Local One:" + tel );
        tel = null;
    }请大家指点迷经,小的不甚感激!!

解决方案 »

  1.   

    谢谢大家的回复,程序种没有递归调用。垃圾回收的时候,heap空间一下子从初始的1984K调到了61120K,不知为何?
    还有,console模式下java程序的内存溢出,还有好的工具推荐?[GC 769K->651K(1984K), 0.0005900 secs]
    [Full GC[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor3]
    [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor4]
    [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor1]
    [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor2]
    651K->432K(1984K), 0.0238370 secs]
    [Full GC 432K->362K(61120K), 0.0306660 secs]
      

  2.   

    2005/12/12 10:00:31 [DEBUG] - remove Stand Remote One:135^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@@aa[GC 1065K->553K(1984K), 0.0004550 secs]
    [GC 1065K->553K(1984K), 0.0004150 secs]
    [GC 787K->556K(1984K), 0.0004140 secs]
    [Full GC 556K->433K(1984K), 0.0214680 secs]
    [Full GC 433K->365K(61120K), 0.0276160 secs]
    java.lang.OutOfMemoryError又挂了!!!:-(
      

  3.   

    调大jvm的内存也不行。[GC 3022K->270K(130112K), 0.0080390 secs]
    [Full GC 270K->270K(130112K), 0.0198970 secs]
    [Full GC 270K->224K(251136K), 0.0246950 secs]
    java.lang.OutOfMemoryError
      

  4.   

    java的缺陷,我也遇到这种情况,在java频繁的操作数据库的时候,方法就是提供效率,改进算法。java占用的资源是比较大的
      

  5.   

    是否初始化一个很大或不断写入hashtable/vector/..., hashtable引用了, vm可不会释放哦?
      

  6.   

    谢谢各位的帮助,问题的原因已经找到,是由于socket读取的数据包不全所致,比如通知传输200000个的,只传输了10个,byte流中有很多空字节数据,数据解析错误所致!同时还发现了下面几个问题:
    1、频繁的数据库操作,是非常占资源的,jdbc有个类占用的资源会越来越大,使用Profiler软件可以很清楚的看到,所以,要尽量少用、优用数据库操作。
    2、Hashtable存入的数据是一个个自定义的对象,里面有2个Vector,作读、写队列用的,很多是没有使用的,却分配了资源空间,属于浪费,需要去掉。
    3、Hashtable是线程安全的,但是是以牺牲时间为代价的,用的不好可能还会引起死锁,1.5推出了synchronized HashMap--concurrentHashMap,据说有了很大的改进。
    4、可能引起的数据竞争问题,详见另贴:
    http://community.csdn.net/Expert/TopicView3.asp?id=4470764谢谢大家。