如何在高性能服务器上进行JVM调优;以便充分利用高性能服务器的硬件资源,有两种JVM调优方案。服务器
1、 采用64位操做系统,并为JVM分配大内存网络
分析:若是JVM中堆内存过小,那么就会频繁地发生垃圾回收,而垃圾回收都会伴随不一样程度的程序停顿。负载均衡
a) 优势:扩大堆内存的话能够减小垃圾回收的频率,从而避免程序的停顿。所以,人们天然而然想到扩大内存容量。而32位操做系统理论上最大只支持4G内存,64位操做系统最大能支持128G内存,所以咱们可使用64位操做系统,并使用64位JVM,并为JVM分配更大的堆内存异步
b) 缺点:堆内存变大后,虽然垃圾收集的频率减小了,但每次垃圾回收的时间变长。若是Full GC频繁发生,那么对于一个网站来讲是没法忍受的。性能
c) 应对办法:所以,对于使用大内存的程序来讲,必定要减小Full GC的频率,若是天天只有一两次Full GC,并且发生在半夜, 那彻底能够接受。要减小Full GC的频率,就要尽可能避免太多对象进入老年代,能够有如下作法:(1)确保对象都是“朝生夕死”的,一个对象使用完后应尽快让他失效,而后尽快在新生代中被Minor GC回收掉,尽可能避免对象在新生代中停留太长时间。(2)提升大对象直接进入老年代的门槛网站
d) 注意:操作系统
1) 64位JDK支持更大的堆内存,但更大的堆内存会致使一次垃圾回收时间过长。线程
2) 现阶段,64位JDK的性能广泛比32位JDK低。代理
3) 堆内存过大没法在发生内存溢出时生成内存快照对象
4) 相同程序,64位JDK要比32位JDK消耗更大的内存
2、 采用32位JVM集群:针对64位JDK的种种弊端,咱们更多的选择32为JDK集群来充分利用高性能机器的硬件资源。
a) 如何实现:在一台服务器上运行多个服务器程序,这些程序都运行在32位的JDK上。而后再运行个服务器做为反向代理服务器,由它来实现负载均衡。因为32位JDK最多支持2G内存,所以每一个虚拟结点的堆内存能够分配1.6G,一共运行10个虚拟结点的话,这台物理服务器能够拥有16G的堆内存。
b) 有啥弊端:
1) 多个虚拟节点竞争共享资源时容易出现问题
2) 很难高效地使用资源池
3) 每一个虚拟节点最大内存为2G
3、 直接内存也会致使内存溢出?
a) 问题分析:在32位JDK中,将1.6G分配给了堆,还有一部分分配给了JVM的其它内存,只有少于0.4G的内存为非JVM内存。咱们知道,若是使用了NIO,那么JVM会在JVM内存以外分配内存空间,这部份内存也叫“直接内存”。所以,若是程序中使用了NIO,那么就要当心“直接内存”不足时发生内存溢出异常了!
b) 直接内存的垃圾回收过程:直接内存虽然不是JVM内存空间,但它的垃圾回收也有JVM负责。直接内存的垃圾回收发生在Full GC时,只有当老年代内存满时,垃圾收集器才会顺便收集一下直接内存中的垃圾。若是直接内存已满,但老年代没满,这时直接内存先是抛出异常,相应的catch块中调用System.gc()。因为System.gc()只是建议JVM回收,JVM可能不立刻回收内存,那么这时直接内存就抛出内存溢出异常,使得程序终止。
4、 JVM崩溃的缘由:当内存溢出时,JVM仅仅会终止当前运行的程序,那么何时JVM会崩溃呢?
5、 异步请求如何形成JVM崩溃:若是一个Web应用使用了较多的异步请求(AJAX),每次主线程发送完请求后都将TCP链接交给一条新的线程去等待服务器回信,那么若是网络不流畅时,这些受委托的线程迟迟等不到服务器的回信,所以保持着TCP链接。当TCP链接过多时,超过JVM的承受能力,JVM就发生崩溃。
6、 如何处理大对象:
a) 在写程序的时候尽可能避免大对象
b) 尽可能缩短大对象的有效时间。对象使用完以后尽快让他失效,以便于垃圾收集器尽快对它进行回收以避免在新生代待的时间过长而进入到老年代。