1.假如一个新的服务性能能足够高,足够强大,但是使用后发现使用效果不理想,经常出现长时间的停顿
这可能是因为64位JDK不限制堆空间的大小,在使用吞吐量优先的收集器的时候,Full GC可能会高达14秒,并且由于程序设计的关系,要将文档从磁盘中提取出来,导致
出现了很多的大对象,而且大对象没有及时的清理,导致很快填满了内存,以至于Full GC
而且,这也和堆空间的极大有关系,在这种12gb的超大堆空间中,必须避免Full GC的出现,或者说减少Full的出现,避免出现长达十几秒的停顿
同时,如果使用了超大堆空间,还会存在一下的问题
1.内存回收导致的长时间停顿
2.可能由于超大的堆空间,导致在OutOfMemoryError的时候无法保存dump文件
3.由于自动地址对齐导致的消耗内存过高
2.在某些情况下,虚拟机经常抛出内存溢出异常,但是
加入了-XX +HeapDumpOnOutOfMemoryError,也不会进行堆转储文件的产生,在监视软件中也没有出现其他问题
最后发现问题在于非JVM内存溢出导致的错误
也就是非堆内存Direct Memory导致的,
Direct Memory现在并不像新生代,老年代一样,发现空间不足就通知收集器进行gc
只能是垃圾收集器在Full GC后,顺手进行清理掉内存中的废弃对象,不然就只能等到内存溢出异常,在catch中进行system.gc了
如果还不行就抛出内存溢出异常了
常见的其他内存区域还有
Direct Memory:可以通过 -XX:MaxDirectMemorySize 调整大小,内存不足进行抛出OutOfMemoryError
栈:通过-Xss进行调节,内存不足的时候抛出StackOverflowError或者OutOfMemoryError了
Socket缓冲区:每个Socket都连接着连个缓冲区,可能导致IOException异常
JNI代码
GC导致的内存消耗
3.调用导致的JVM崩溃
举一个例子:两个系统进行集成,通过异步的方式调用web服务,但是两个系统之间的处理速度不对等,会导致一方的积累了过多的web服务没有调用完成,或者完成返回,导致等待返回的线程越来越多,
最后服务器进程崩溃,解决方案, 还是采用消息队列比较好
4.不恰当的数据结构导致内存占用过大
假如有一个服务器,采用64位虚拟机,平常一切无问题,但是在每10分钟加载一个80MB的数据文件到内存中
导致产生了超过了100万个HashMap 的集合,导致了长时间的停顿时间,具体日志如下
这种原因一目了然,就是在加载后产生了大量对象,在产生后无法立即回收,导致的多次Miror GC 乃至于 Major GC
但是其根本原因还是由于这种加载方式,加上HashMap这种存储结构效率低导致的