所以,我正在运行一个java服务器(特别是Winstone:http://winstone.sourceforge.net/)
像这样:java -server -Xmx12288M -jar /usr/share/java/winstone-0.9.10.jar --useSavedSessions = false --webappsDir =/var/servlets --commonLibFolder =/usr/share/java
这在过去运行良好,但现在需要将更多的东西加载到内存中,而不是以前.
奇怪的是,根据'top',它有15.0g的VIRT(ual内存),它的RES(ident set)是8.4g.一旦达到8.4g,CPU就会挂起100%(即使它是从磁盘加载的),最终,我得到了Java的OutOfMemoryError.据推测,CPU挂起100%是Java做垃圾收集.
那么,我的问题是,是什么给出的?我给了它12个演唱会!并且只有在它投入之前才使用8.2演出.我究竟做错了什么?
哦,我正在使用java版"1.6.0_07"Java(TM)SE运行时环境(版本1.6.0_07-b06)Java HotSpot(TM)64位服务器VM(版本10.0-b23,混合模式)
在Linux上.
谢谢,马特
奇怪的是,根据'top',它有15.0g的VIRT(ual内存),它的RES(ident set)是8.4g.一旦达到8.4g,CPU就会挂起100%(即使它是从磁盘加载的),最终,我得到了Java的OutOfMemoryError.
我认为你是在误解事物."-Xmx12288M"选项不保留物理内存.而是设置Java堆大小的上限.Java还需要非堆对象的内存; 例如permgen空间,代码空间,内存映射文件等.对于12g堆+ JVM使用/共享的非堆内存来说,最多可以添加15g.
top作为RES报告的8.4g是当前用于运行JVM的物理内存量.它与Java堆的大小没有直接关系.实际上,当操作系统虚拟内存系统交换不同进程的页面时,您会期望RES编号上下移动.这完全超出了JVM的控制范围.
据推测,CPU挂起100%是Java做垃圾收集.
是.这通常会发生什么.
我可以想到三种可能的解释:
最有可能的是,操作系统无法为您的JVM提供所需的内存,因为没有足够的交换磁盘空间.例如,如果你有2个进程,每个进程有15g的虚拟内存,那就是30gb.鉴于您有24g物理内存,您将需要至少8g(可能更多)的交换空间.如果可分配给用户进程的物理内存量+交换空间量小于进程使用的总虚拟空间,则OS将开始拒绝JVM扩展堆的请求.您可以运行"swapon -s"以查看可用/正在使用的交换空间量.
您的应用程序可能真的使用了您已经说过它可以使用的所有12g堆,这还不够.(也许你有一个存储泄漏.也许它真的需要更多的内存.)
有可能(但极不可能)有人设定了流程限制.您可以使用shell builtin'ulimit'命令查看是否已完成此操作; 有关详细信息,请参阅"man ulimit".
编辑
如果您使用-verbose:gc和-XX:+PrintGCDetails选项,GC可能会为您提供更多有关正在发生的事情的线索.特别是,它会告诉你内存不足时Java堆的大小.
您可以编写一个简单分配并且不会释放大量内存的Java应用程序,并查看在使用与您当前使用的相同选项运行时因OOM错误而导致分配的数量.(我不认为这会告诉你任何新的东西. 编辑2实际上,如果你以@Dan建议的方式运行它会告诉你一些事情!)
如果(似乎很可能)真正的问题是你没有足够的交换空间,那么在Java方面你无法做任何事情来解决这个问题.您需要重新配置系统以获得更多的交换空间.请参阅您的Linux系统管理文档,该man换页swapon,mkswap等等.
| 归档时间: |
|
| 查看次数: |
10541 次 |
| 最近记录: |