日期:2014-05-20  浏览次数:20906 次

又踩到一个坑——JAVA虚拟机最大内存
最近一直在优化项目,然后想把一个查询频繁的表加载到内存中建立一个HashMap结构,然后tomcat各种listenstart报错,我因为也不太懂JAVA,吭哧吭哧搜了一下午也没搞定。。。

然后问了组里经验丰富的人,说可能是加载的内存过大。然后我一看,我去,这个小破表竟然占了6G。。然后我加了一些筛选条件,大概4G的样子。

然后按网上说的把tomcat的Xmx搞到4500m。。。。然后满怀希望启动,一看日志,我去,超出限制了。百思不得其解啊,又去问人家。人家回来让看看机器是多少位的,说32位的JAVA虚拟机最大内存好像只能开到2G左右。64G可以很大。然后我一看,果然是32位的。。。。

然后我就没有办法了。。。各位,谁能给我解释一下tomcat为啥根据32位、64位限制JAVA虚拟机的大小。机器有12G内存,空闲有10G。。。但是竟然不支持。真是郁闷的不行,然后用servlet访问一个接口,就报NullPointerException,我估计是因为数据没加载到内存,这个接口一查发现数据是空的,然后就扔过来一个异常。(这是我猜的,希望你能根据经验给我判断一下。。)

谢谢各位了。。谁能给点建议更好,明天跟mentor商量一下,换个64的机器来搞~~

------解决方案--------------------
首先你把表里的东西都加载到内存当中,这本身就不合理。就不能分页查询?
其次32位操作系统,支持内存到4G,而系统已经占用一部分内存,所以你的程序可用内存更少。而且如果是32位系统,你插入8G/16G内存条,可识别内存也不会超过4G。
------解决方案--------------------
从你的这个问题看,即使给了你64位系统也不一定能解决你的问题。

这么大的数据量全部加载到内存的HashMap中,这种设计肯定是有问题的。

HashMap虽然通过hash值进行了快速定位的优化,但是归根到底HashMap的定位方式还是遍历,小数据量定位很快,但是大数据量性能将会非常的差,性能远没有数据库的索引采用Btree之类的结构搜索来的快。所以可能你是想优化系统,结果把系统给优化到坑里了。
------解决方案--------------------
我很奇怪,公司为什么要你这个完全不懂系统设计的人去优化项目。看你对内存和架构的理解,似乎无法完成这个工作...

一个6GB数据的表,是不可以这样放入内存的- -。而且很多时候,也不需要这种优化,通常只要建立索引和一些逻辑处理上的优化基本上就能适用所有的业务系统。如果并发量实在大,流量巨大,实在是数据太频繁适用,那就要硬件的支持和良好的设计了,就算数据使用很频繁,也不可能6GB数据都很频繁- -,只要统计出6GB中哪些频繁然后缓存就可以了,就像java的内存回收机制。

如果是数据分析系统的话,我只能告诉你,以你目前的硬件配置还无法完成任务,当然还需要一个针对性的设计以及大量的代码优化,着同样不是以你现在的水平能够完成的,需要一个很资深的在大数据处理上有经验的人来处理。