引入:
我们有时候经常遇到Liferay运行一段时间之后服务器瘫痪了,这时候其实很希望的做法就是用管理员登陆Liferay控制面板中(Dockbar->Control Panel->Server->Service Administration)然后实时调用一些操作,比如垃圾回收,紧接着,我们就可以从仪表盘中看到更新后服务器的内存情况或者其他情况了。那么这其中隐藏什么样的秘密呢?比如如何做到垃圾回收呢?仪表盘是如何更新呢?
调试分析:
我们还是从前端开始,当我们初次去看Liferay服务器系统信息时候,看到的内存开销如下:
当我们点击下方的动作:比如说gc:
它会去触发struts action为/admin_server/edit_server,并且命令cmd为gc
我们很容易在struts-config.xml中找到对应的Action类为EditServerAction:
因为我们的 cmd是gc,所以会走以下分支:
并且调用gc()方法:
这可以看出,实际它是调用当前应用对应的运行时,让其调用gc()方法来强制进行垃圾回收。关于这个Runtime.getRuntime.gc()和System.gc()区别我不想再说了,相关文章一大堆。
我们现在来研究更感兴趣的话题,当这个gc()垃圾回收完成之后,怎么去更新系统信息仪表盘。很容易就找到,其实这个仪表盘对应的代码是在server.jspf 这个页帧中(因为我们的tab选的是"server"):
我们跳过许多不重要的行,可以发现,直到第656行,就开始为下面的仪表盘准备数据了:
首先,第656到第660行通过当前应用的运行时向运行环境所要总内存(totalMemory)和未被使用的内存(freeMemory)来计算出已经被使用的内存(usedMemory)。
然后,它会在666行算出使用的内存占据总内存的百分比数值(% *100),并且吧这个值存入dataset中,
然后668行初始化MeterPlot对象,这个对象代表了一个拥有指针的刻度盘,然后封装了相应的数据。被JFreechart使用,它会显示这个刻度面板的颜色,标尺等信息。
然后第670行则会去创建一个JFreeChart对象,这个图标的名字就是used-memory/total-memory的国际化文本:
并且吧MeterPlot中图形的全部信息plot传入到JFreeChart对象中。
最后,第673行会创建一个图片对象,然后插入到当前的页面中:
现在我们更加感兴趣的是这个图像是如何创建的,名字在哪里?位置在哪里?
宏观上看,它会调用ServletUtilities.saveChartASPNG()方法,吧jfreechart对象以及图片的宽度高度都传递给这个方法,用于生成图片。我们来看下实现:
首先,它会在180行去创建一个临时目录,这个临时目录在哪里呢?我们看下createTempDir()的调用:
现在明白了,原来临时目录在java.io.tmpdir中,而这个在我们服务器上是
见java.io.tmpdir动态参数,所以我们知道这个临时目录创建在/app/Liferay/RI/liferay-portal-6.1.0-ce-ga1/tomcat-7.0.23/temp,也就是$CATALINA_TMP_DIR下:
然后我们在第183行获取单次使用的图片文件的前缀是:jfreechart-onetime-
然后在第185行,根据文件的扩展名(png),前缀(prefix)来创建相应的图片文件的File对象:
我们验证我们的$CATALINA_TMP_DIR,果然发现了一个图片文件被创建了:
但是其大小为0 ,这很正常,因为我们只创建了File对象,还没有问其添加图片内容。
添加内容的代码是在第187行调用重载的ChartUtilities的saveChartAsPNG方法实现的:
可以发现,它先创建了一个FileOutputStream指向目标的图片文件,然后写入这个文件输出流,最终是调用的通过JFreechart创建一个bufferedImage,然后利用EncoderUtil吧这个图片编码成png格式,并且最终写入File对象对应的文件输出流中
现在我们对比这个图片文件,就发现它尺寸不再是0了(现在是9253字节):
因为是一次性文件,所以在第189行调用registryChartForDeletion方法注册将这个图片文件删除。
我们用浏览器的Web调试器看,果然这个资源文件被加载进来了:
最终会显示在页面上。
总结:
(1)在控制面板中调用garbage collector去回收内存时,其本质是调用的当前Liferay应用对应的运行时Runtime的gc()方法,用于强制的进行一次垃圾回收。
(2)回收的结果会实时的反映到上方的仪表盘中和数据区。这个仪表盘是JFreechart画的,它会从Runtime运行时中会去必要信息,然后构建图。然后JFreechart会在tomcat的临时目录创建一个临时的png格式的文件,打开文件输出流执行该文件,用JFreechart创建BufferedImage最后输出到这个输出流中,然后页面上会以 src的形式加载这个新生成的图片文件并且显示到页面上。
(3)一旦执行完,因为这个临时的图片文件PNG是一次性的,所以它会被框架从tomcat临时目录中移除。