従来ヒープ情報のようなリアルタイム更新するグラフを実装する場合、
- サーバサイドで画像を生成し、ブラウザへ送る
- サーバからデータを受け取って、ブラウザがアプレットでグラフを描画する
のどちらかだったと思います*1。
前者はサーバに負荷がかかるため、後者が一般的でしょう。けどアプレットって起動が結構重いので、イライラしますね。
そこへ第3の選択肢が現れました!Google ChartはサーバでもクライアントでもなくGoogleインフラが描画をやっちゃってくれます。早速作ってみました。

index.html
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=Shift_JIS">
<title>Simple Console</title>
<script type="text/javascript" src="jquery-1.2.3.js"></script>
<script>
var NUM_OF_SAMPLES = 60; // 表示サンプル数
var timerId;
var maxMemory = 0;
var maxChd;
var totalChd;
var usedChd;
function init() {
// 同期でmaxMemoryを取得
jQuery.ajax({
async: false,
url: "resource.jsp",
data: "cmd=maxMemory",
success: function(data){maxMemory = data}
});
// 初期データ文字列を組み立て
maxChd = "100";
totalChd = "0";
usedChd = "0";
for (i = 1; i < NUM_OF_SAMPLES; i++) {
maxChd += ",100";
totalChd += ",0";
usedChd += ",0";
}
// 周期呼び出し
timerId = setInterval("loadChart()", $("#updatePeriod").attr("value") * 1000);
}
function loadChart() {
// 非同期でヒープ情報を取得
jQuery.get("resource.jsp", "cmd=heap",
function(dataStr){buildChart(dataStr)});
}
function buildChart(dataStr) {
var data = dataStr.split(",");
// maxMemoryに対する比を0〜100で表現
totalChd += "," + Math.round(data[0] * 1000 / maxMemory) / 10;
usedChd += "," + Math.round(data[1] * 1000 / maxMemory) / 10;
// データ文字列をずらす
totalChd = totalChd.substring(totalChd.indexOf(",") + 1);
usedChd = usedChd.substring(usedChd.indexOf(",") + 1);
// URL組み立て
var url = "http://chart.apis.google.com/chart?" +
"chs=480x320&cht=lc&chxt=x,y&chco=ff0000,00ff00,0000ff&chdl=Max|Total|Used&" +
"chxl=0:||1:||" + Math.round(maxMemory / (1024 * 1024)) + "MB&" +
"chd=t:" + maxChd + "|" + totalChd + "|" + usedChd;
// srcを差し替える
$("#heapChart").attr("src", url);
// URLをデバッグ出力
$("#debug").html(url);
}
function changePeriod() {
clearInterval(timerId);
timerId = setInterval("loadChart()", $("#updatePeriod").attr("value") * 1000);
}
function gc() {
// 非同期でGCを実行
jQuery.get("resource.jsp", "cmd=gc");
}
</script>
</head>
<body onload="init()">
<img id="heapChart" src="" alt="heap chart">
<br>
<form name="form1">
更新周期<input type="text" id="updatePeriod" size="5" value="1">秒
<input type="button" value="周期変更" onclick="changePeriod()">
<br>
<input type="button" value="GC" onclick="gc()">
<br><br>
<div id="debug" style="width:480px;word-wrap:break-word;word-break:break-all;"></div>
<br>
</form>
</body>
</html>resource.jsp
<%@page session="false" contentType="text/html; charset=Shift_JIS" %>
<%@page import="java.util.*" %>
<%
response.setHeader("Expires", "-1");
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
String cmd = request.getParameter("cmd");
if (cmd.equals("maxMemory")) {
Runtime runtime = Runtime.getRuntime();
out.print(
runtime.maxMemory()
);
} else if (cmd.equals("heap")) {
Runtime runtime = Runtime.getRuntime();
out.print(
runtime.totalMemory() + "," +
(runtime.totalMemory() - runtime.freeMemory())
);
} else if (cmd.equals("gc")) {
System.gc();
}
%>resource.jspは単純にヒープ情報のデータだけ返します。index.htmlは非同期でjspを呼び出し、Google ChartのURLを組み立て、imgタグのsrc属性を差し替えます。1秒間隔の更新でも全く問題ありません。さすがGoogle!
JavaScriptはまだまだビギナーなのでもっさいコードがあるかもしれません。jQueryを使ってみました。コードが少しはすっきりしたかな?
http://toshiyakobayashi.googlepages.com/scon.zip
からダウンロードできるようにしました。解凍し、Tomcatならwebapps/Rootの下に、JBossならdeploy/jboss-web.deployer/ROOT.warの下にsconディレクトリをコピーしたらOKです。
*1:どちらにしてもライブラリはJFreeChartあたり