Java 7 から Java 8 ランタイムへの移行

このページでは、既存の App Engine アプリを Java 7 ランタイムから Java 8 ランタイムに移行する方法について説明します。App Engine の Java ランタイムは OpenJDK に基づいています。

アプリ用の Java 8 ランタイムの指定

Java 8 ランタイムでアプリを実行するには:

  1. appengine-web.xml ファイルに <runtime>java8</runtime> を追加します。

    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
      <runtime>java8</runtime>
      <threadsafe>true</threadsafe>
    </appengine-web-app>
  2. アプリを再デプロイします。

サポート対象外サービスの移行

Java 7 ランタイムで使用可能だった非推奨のサービスの一部が、Java 8 ランタイムではサポートされていません。ご使用のアプリを推奨されている代替サービスに移行し、Java 8 に移行する前に、それらの変更についてアプリを Java 7 ランタイムでテストすることをおすすめします。

以下の非推奨のサービスは、Java 8 ランタイムでは使用できません。

非推奨のサービス 推奨される代替サービス
Cloud Endpoints v1 v2 に移行します。このプロダクトは Cloud Endpoints Frameworks に名前が変更されました。この移行によって、ウェブ、Android、または iOS のアプリを変更する必要が生じる場合があります。
AppStats(appengine-api-labs jar) Cloud Trace に移行します。Java 8 ランタイムでは、アプリが com.google.appengine.tools.AppstatsFilter クラスを使用すると SDK によってエラーが生成されます。web.xml から AppstatsFilter へのすべての参照を必ず削除してください。

Java 8 では、再パッケージ化されるクラスで新しいインポートパスを設定する必要があります。たとえば、アプリで com.google.appengine.repackaged.com.google.common.base.Optional を使用していた場合、クラス名の前に $ が付く com.google.appengine.repackaged.com.google.common.base.$Optional をインポートする必要があります。

java.net.HttpURLConnection を使用する無料アプリの移行

アプリで課金が有効になっていない場合、java.net.HttpURLConnection クラス、またはこのクラスを使用する Google クライアント ライブラリを使用して HTTP(S) リクエストを行うと、ランタイム エラーが発生します。これを回避するには、アプリの appengine-web.xml<url-stream-handler>urlfetch に設定します。

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <!-- ... -->
  <url-stream-handler>urlfetch</url-stream-handler>
  <!-- ... -->
</appengine-web-app>

または、urlfetch を指定する代わりに、アプリケーションの課金を有効にして、デフォルトの native 設定を使用します。アプリの費用が Java 7 で実行していたときより増えることはないはずです。アプリで X-Appengine-Inbound-Appid HTTP ヘッダー(モジュール間通信に使用)を使用する場合は、必ず urlfetch を使用してください。

デフォルトのファイルのエンコードの変更

Java 8 では、App Engine のデフォルトのファイルのエンコードが Java 7 で使用されていた US-ASCII から UTF-8 に変更されています。Java 8 でデフォルトのエンコードを US-ASCII に戻すには、appengine-web.xml に次の行を追加します。

 <system-properties>
   <property name="appengine.file.encoding" value="US-ASCII"/>
 </system-properties>

一部の文字が ASCII セットに含まれず、アプリケーションで someString.getBytes().length == someString.length() などを想定している場合には、エラーが発生する可能性があります。US-ASCII エンコードの場合、非 ASCII 文字は「?」にマップされますが、UTF-8 エンコードの場合も同じ処理が行われるとは限らないためです。

たとえば、Éamonn.getBytes() を呼び出して 16 進数バイトを出力すると、UTF-8 では c3 89 61 6d 6f 6e 6eÉamonn)となりますが、US-ASCII では É のエンコード値が異なるため 3f 61 6d 6f 6e 6e?amonn)となります。

Java 8 ランタイムの機能を十分に活用する

以下に、Java 8 ランタイムに移行する利点の一部を示します。

  • Jetty 9 で、サーブレット アノテーションを含め、Servlet 2.5 と 3.1 の両方のウェブアプリがサポートされます。
  • すべての標準 Java クラスが使用可能になり、クラスの許可リストがなくなります。
  • /tmp ファイル システムが書き込み可能になります。ただし、これによってアプリの RAM 割り当てが使われます。
  • すべての Java スレッドでネットワーク I/O を実行できるようになりました。App Engine API の呼び出しは引き続き、リクエスト スレッド、または Thread Manager API によって作成されたスレッドのいずれかに存在している必要があります。
  • Stream API、Lambdas、Date / Time API をはじめとする Java 8 の言語全体がサポートされるようになりました。