今明らかにされる 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クラスの試用にいたってはサーバ障害っぽい事態まで引き起こしてしまった。ごめんなさいごめんなさい。