今明らかにされる Google App Engine for Java の実行環境。

※ ひひひ、初めて釣りっぽいタイトルを入れてみたよ。

テスト用のServletを入れて、少しGoogle App Engine for Javaの実行環境を探ってみた。

  • HTTP上のサーバ名は「Google Frontend」
  • システムプロパティos.nameの値が「Linux」なので、Servletを実行しているのはLinux機。os.archが見あたらないけど、まず間違いなくIA-32アーキテクチャ機じゃないかな。
  • Runtime.availableProcessors()によると搭載プロセッサ数は1337個。ははは、クラウドだね。
  • メモリの最大リミットは100MB。ヒープ領域長はすでにリミットに到達済み。リクエスト中に空きメモリを見たら6MBほど。大丈夫なのこれ?いざとなればソフト参照なキャッシュとかが解放されるんだよね?
  • システムプロパティを見るとVMはSunMicrosystems社提供。サーバ用VMでなくクライアント用VMなの?
  • アプリ固有の値がシステムプロパティuser.dirに入っているということは、アプリごとに違うVMを割り当てているのかな?ProtectionDomainとかを見て違う値を設定しているのかな?まさかアプリごとにブートストラップクラスローダから異なってたりする?
  • 1リクエスト内でSystem.nanoTime()を2回連続して呼んだときの差分は20〜30msec程度。(Pen4+WinXP+Tomcatで同じことをすると1msを切る)。クラウド内でnanoTime()値の同期が取られている保証はないので、リクエスト間でのnanoTime()の比較はたぶんあてにならない。
  • 時刻設定は正確。標準時に対しておそらく1000ms以内の精度。NTPでクラウド間の時計を同期しているのかな。
  • サーブレットのクラスローダはcom.google.apphosting.runtime.security.UserClassLoader。これより上位の移譲先が誰かは不明。
  • セキュリティマネージャもしっかり入っている。おそらくGoogle製。com.google.apphosting.utils.security.SecurityManagerInstaller$CustomSecurityManager。
  • 標準入力はcom.google.apphosting.runtime.security.EmptyInputStream。標準出力はcom.google.apphosting.runtime.security.shared.intercept.java.lang.System_$LogPrintStream。標準エラーはcom.google.apphosting.runtime.security.shared.intercept.java.lang.System_$LogPrintStream。
  • 日本語用Charsetは一通り利用可能。「EUC-JP」「ISO-2022-JP」「Shift_JIS」「UTF-8」「windows-31j(≒MS932)」。
  • システムプロパティfile.encodingの値は「ANSI_X3.4-1968」。いわゆるアスキーコードなので0x5Cはバックスラッシュで0x7Eはチルダ記号。UTF-8と異なり、日本語は使えないはず。デフォルトのCharsetは「US-ASCII」。コンストラクタString(byte[] bytes)で日本語をデコードするのはまず無理じゃないかな。
  • デフォルトのタイムゾーンは「UTC」。日本標準時刻より9時間遅い。困る人はTimeZone.getTimeZone("Asia/Tokyo")などで得たタイムゾーンを明示的に使う必要がある。Googleの担当者が「JDK DST タイムゾーン更新ツール」とかでまめにメンテナンスしてるか否かは不明。
  • デフォルトのロケールは「en_US」。困る人はLocale.JAPANなどのロケールを明示的に使う必要がある。


読み込み可能なシステムプロパティは以下の通り。ちなみに環境変数はきれいさっぱり消されている。

プロパティ名
java.version 1.6.0_13
java.class.version 50.0
java.vendor Sun Microsystems Inc.
java.vendor.url http://java.sun.com/
java.vm.name Java HotSpot(TM) Client VM
java.vm.version 1.6.0_13
java.vm.vendor Sun Microsystems Inc.
java.vm.specification.name Java Virtual Machine Specification
java.vm.specification.version 1.0
java.vm.specification.vendor Sun Microsystems Inc.
java.specification.name Java Platform API Specification
java.specification.version 1.6
java.specification.vendor Sun Microsystems Inc.
line.separator なんだっけ
file.separator /
path.separator :
os.name Linux
file.encoding ANSI_X3.4-1968
user.dir /base/data/home/apps/アプリ名/バージョン名+ごにょごにょ

Servlet呼び出しのスタックトレースは↓こんな感じ。SDKに入っている開発用サーバもそうだけど、ServletコンテナにJettyを使っているらしい。ああ、なんとかしてNetBeansからデプロイできないかな。

 at ほげパッケージ.Servlet.doGet(Servlet.java:75)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
 at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
 at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
 at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
 at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
 at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
 at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
 at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
 at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
 at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:237)
 at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
 at org.mortbay.jetty.Server.handle(Server.java:313)
 at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)
 at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)
 at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:63)
 at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
 at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:125)
 at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:235)
 at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4547)
 at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4545)
 at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24)
 at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:359)
 at com.google.net.rpc.impl.Server$2.run(Server.java:792)
 at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56)
 at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:489)
 at com.google.net.rpc.impl.Server.startRpc(Server.java:748)
 at com.google.net.rpc.impl.Server.processRequest(Server.java:340)
 at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:422)
 at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319)
 at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290)
 at com.google.net.async.Connection.handleReadEvent(Connection.java:419)
 at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:733)
 at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207)
 at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:101)
 at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:249)
 at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:373)
 at java.lang.Thread.run(Unknown Source) 

InetAddressクラスとかはそもそも存在すらしないらしい。

NetworkInterfaceクラスの試用にいたってはサーバ障害っぽい事態まで引き起こしてしまった。ごめんなさいごめんなさい。