深入理解_JVM内存管理调优案例分析与实战10

1、高性能硬件上的程序部署策略

目前常用2种方式:

(1)通过64位JDK来使用大内存:

使用第一种方式关键:

<1>控制应用程序的Full GC频率。譬如10多个小时甚至一天才出现一次Full GC。

关键:大多数对象的生存时间不应该太长,保证老年代空间的稳定。

在大多数网站形势的应用里,主要对象的生存周期都是请求级或页面级的,会话级和全局级的长生命对象相对较少,控制住Full GC。

需要考虑的问题:

<1>内存回收导致的长时间停顿;

<2>现阶段,64位JDK的性能测试结果普遍低于32位JDK;

<3>需要保证程序稳定,因为这种方式产生堆溢出几乎就无法产生堆转储快照;

<4>相同程序在64位JDK中消耗的内存一般比32位JDK大,这是由于指针膨胀及数据类型对齐补白等因素导致。

(2)使用若干32位虚拟机逻辑集群来利用硬件资源:(现在阶段常采用的方案)

具体做法:

<1>启用多个应用服务器进程,给每个服务器进程分配不同的端口;

<2>前端搭建一个负载均衡器,利用反向代理的方式来分配访问请求。

可能会遇到的问题:

<1>尽量避免节点竞争全局的资源,最典型的就是磁盘竞争;

<2>很难最高效率地利用某些资源池,譬如连接池,一般都是在各个节点建立自己的独立的资源池,导致一些节点资源池满了而另外一些节点仍有比较多的空余。尽量使用集中式的JNDI。

<3>各个节点仍然不可避免的受到32位的内存限制;

<4>大量使用本地缓存(如大量使用HashMap作为K/V缓存)的应用,在逻辑集群中会造成较大的内存浪费,因为每个逻辑节点上都有一份缓存,这时可以考虑把本地缓存改为集中式缓存。

2、集群间同步导致的内存溢出

3、堆外内存导致的溢出错误

问题现象:

<1>不定时抛出内存溢出异常;

<2>加入:-XX:+HeapDumpOnOutOfMemoryError,没有任何反应,抛出内存溢出异常时什么文件都没有产生。

找出问题:

<1>使用jstat实时监控,仍然很正常;

<2>最后通过系统日志找到异常堆栈。

分析错误原因:

<1>32位windows平台,内存限制2GB,其中java堆分配了1.6GB,而Direct Memory(参见《深入理解JVM内存管理_1、运行时数据区域》中的直接内存部分的介绍)并不算在1.6GB的堆之内,只有去剩下的0.4GB中分配;

<2>垃圾收集进行时,虚拟机虽然会对Direct Memory继续回收,但是Direct Memory却不像新生代和老年代那样,发现空间不足就通知收集器进行垃圾回收,它只能等待老年代满了之后Full GC,然后随便帮它清理内存的废弃对象。否则,它只能等到抛出内存溢出异常时,先catch掉,再在catch块里面大喊一声“System.gc()”。要是虚拟机还是不听(譬如打开:-XX:+DisableExplicitGC开关),那就只能看着堆中还有许多空闲内存,自己却不得不抛出内存溢出异常了。

通过问题得到的启示:

<1>Direct Memory:可通过-XX:MaxDirectMemorySize调整大小,内存不足时抛出OutOfMemoryError或OutOfMemoryError:Direct buffer memory。

<2>线程堆栈:可通过-Xssz调整大小,内存不足时抛出StackOverFlowError(纵向无法分配,即无法分配新的栈帧)或者OutOfMemoryError:unable to create new native thread(横向无法分配,即无法建立新的线程。)

<3>Socket缓存区:每个Socket连接都Receive和Send两个缓存区,分别占大约37K和25K的内存,连接多的话这块内存占用也比较客观,如果无法分配,抛出:IOException:Too many open file异常。

<4>JNI代码:如果代码中使用JNI调用本地库,那本地库使用的内存也不在堆中。

<5>虚拟机和GC:虚拟机和GC的代码执行也要消耗一定的内存。

4、外部命令导致系统缓慢:

问题现象:

<1>CPU使用率很高,而且发现并不是user应用占用的高。

<2>发现是“fork”系统调用,“fork”系统调用时Linux用来产生新进程的。在java虚拟机中,java代码最多只产生线程,不应当有进程的产生。

找出问题:

<1>使用java的Runtime.getRuntime().exec()来调用shell脚本来获取系统信息,该方式非常消耗CPU和内存。

解决办法:

通过java的API来获取系统信息即可。

5、服务器JVM进程崩溃:

问题现象:

<1>集群节点的虚拟机进程自动关闭的现象。

<2>异常:java.net.SocketException:Connection reset

找出问题:

<1>两个系统之间需要同步信息,而两个系统的响应速度不对称(尽管使用了异步的机制),导致主动发起请求(且速度快的系统)时间越长就累计了越多的服务没有调用完成,在等待的线程和Socket连接越来越多,最终超过了虚拟机的承受能力后使虚拟机进程崩溃。

解决办法:

将异步调用模式改为生产者/消费者模式的消息队列实现后,系统恢复正常。

时间: 2024-11-03 20:46:44

深入理解_JVM内存管理调优案例分析与实战10的相关文章

《深入理解Java虚拟机》调优案例分析与实战

上节学习回顾 在上一节当中,主要学习了Sun JDK的一些命令行和可视化性能监控工具的具体使用,但性能分析的重点还是在解决问题的思路上面,没有好的思路,再好的工具也无补于事. 本节学习重点 在书本上本节的主要内容是讲作者在工作过程中对调优的一些经验实战.对于我们读者来说,重点是学习作者分析解决问题的具体思路.当然不能离开书本的内容,作者利用的是上一节所介绍到的工具去解决他所遇到的问题.但本人的工作环境跟书本上的教程不一致,但思路大同小异.所以在本章的学习笔记当中,还是结合自身的情况,聊聊调优这事

第五章 调优案例分析与实战

案例1: 15万PV/天左右的在线文档类型网站最近更换了硬件系统,新的硬件为4个CPU.16GB物理内存,操作系统为64位CentOS 5.4 , Resin作为Web服务器.整个服务器暂时 没有部署别的应用,所有硬件资源都可以提供给这访问量并不算太大的网站使用.管理员为 了尽量利用硬件资源选用了64位的JDK 1 . 5 ,并通过-Xmx和-Xms参数将 Java堆固定在12GB.使用一段时间后发现使用效果并不理想,网站经常不定期出现长时间失去响应的情况. 监控服务器运行状况后发现网站失去响应

深入理解_JVM内存管理典型配置举例09

以下配置主要针对分代垃圾回收算法而言: 1.堆大小设置: 年轻代的设置很关键JVM中最大堆大小有三方面限制: (1)相关操作系统的数据模型(32-bt还是64-bit)限制: (2)系统的可用虚拟内存限制: (3)系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作系统对内存无限制.在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m. 典型设置: (1)场景一: java -Xmx3550m -Xms3550m -X

深入理解_JVM内存管理垃圾收集器05

1.垃圾收集器(内存回收方法的具体实现): 名词解释: 并行(Parallel):多条垃圾线程并行工作,但是此时用户线程仍然处于等待状态. 并发(Concurrent):指用户线程与垃圾收集线程同时执行(并不一定是并行的,可能会交替执行),用户程序继续运行,而垃圾收集程序运行于另一个CPU上. HotSpot虚拟机包含的所有收集器如下图: 说明: (a)JDK1.6_Update14之后引入了Early Access版G1收集器. (b)如果两个收集器之间存在连线,就说明它们可以搭配使用. <Y

深入理解_JVM内存管理对象引用03

1.对象引用: (a)对象状态的判断: <1> 引用计数算法:无法解决对象相互引用的问题. <2> 根搜索算法:主流的判断对象是否存活的算法. (1)基本思路:通过一系列的名为:"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相关联时,证明此对象是不可用的,所以它们将会被判断为是可收回的对象. (2)Java中,GC Roots的对象包括下面几种:

深入理解_JVM内存管理内存分配和回收策略06

解决两个问题: 1.对象分配内存: 2.回收分配给对象的内存. 本节详细讲解分配的问题: 名词解释: 新生代GC(Minor GC):指发生在新生代的垃圾回收动作,非常频繁,回收速度很快. 老生代GC(Major GC/Full GC):指发生在老生代的垃圾回收动作,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对),速度一般会比Minor GC慢10倍. 打印日志说明: <1> DefNew:串行GC方式(Serial GC). <2> ParNew:Par

深入理解_JVM内存管理JDK监控工具与故障处理工具07

1.jps: JVM process Status Tool,显示系统所有的HotSpot虚拟机进程以及进程的本地虚拟机的唯一ID(LVMID,Local Virtual Machine Identifier). 对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID,Process Identifier)是一致的.如果启动了多个虚拟机进程,就需要显示主类的功能才能区分了. jps命令格式: jps [option] [hostid] jps主要选项: -v :输出虚拟机进程启动时JVM

深入理解_JVM内存管理JDK监控工具与故障处理工具08

Jconsole: Visial VM: 1.主要功能: (1)显示虚拟机进程及进程的配置和环境信息(jps,jinfo): (2)监视应用程序的CPU.GC.堆.方法区及线程信息(jstat,jstack): (3)dump及分析堆转储快照(jmap,jhat): (4)方法级的程序运行性能分析,找出被调用最多.运行时间最长的方法: (5)离线程序快照:收集程序的运行时配.线程dump.内存dump等信息建立一个快照,可以将快照发送开发者进行bug处理: (6)其他plus可能性. 2.生成和

深入理解_JVM内存管理垃圾收集算法04

1.垃圾收集算法(方法论): 定义:JVM通过GC来回收堆和方法区中的内存. GC的基本原理:首先会找程序中不再被使用的对象:然后回收这些对象所占用的内存. 算法分类: (1) 按照基本回收策略分: <1>引用计数(Reference Counting): 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此算法最致命的是无法处理循环引用的问题. <2> 标记-清除(Mark-Sweep): Before G