Java 8 Runtime Environment

With App Engine, you can build web applications that use Google's scalable infrastructure and services. App Engine runs your web application using a Java 8 JVM. App Engine invokes your app's servlet classes to handle requests and prepare responses in this environment.

The App Engine platform provides many built-in API services that your code can call. Your application can also configure scheduled tasks that run at specified intervals.

Specifying the Java 8 runtime for your app

To make your app use the Java 8 runtime, add the following line to your appengine-web.xml file:

<runtime>java8</runtime>

The appengine-api.jar file included with the Google Cloud CLI under platform/google_appengine/google/appengine/tools/java/lib/impl/appengine-api.jar represents the App Engine API for Java. You can also access this file using the Maven repository which lists all the versions.

You select the version of the API your application uses by including this JAR in the application's WEB-INF/lib/ directory, or use Maven to handle dependencies. If a new version of the Java runtime environment is released that introduces changes that are not compatible with existing apps, that environment will have a new major version number.

Using Maven to handle dependencies

You can use Maven to manage all of the dependencies. For example, this pom.xml entry includes the latest App Engine API (Rappengine-api-1.0-sdk) available from Maven Central:

<dependency>
    <groupId>com.google.appengine</groupId>
    <artifactId>appengine-api-1.0-sdk</artifactId>
    <version></version>
</dependency>

The sandbox

The App Engine Java runtime distributes requests for applications across multiple web servers and prevents one application from interfering with another. An App Engine app must not respond slowly. A web request to an application must be handled within the request timeout limit. Processes that exceed this limit to respond are terminated to avoid overloading the web server.

Note that the only place where users can write files is the/tmp directory. Files in /tmp will consume the memory allocated to your instance. The files stored in this location are only available to this instance and only for the lifetime of this specific instance.

The usual way for your application to get resource files is to package the files you rely on with your application under WEB-INF, then load them from your app using Class.getResource(), ServletContext.getResource(), or similar methods. By default, all files in the WAR are "resource files". You can exclude files from this set using the appengine-web.xml file.

Class loader JAR ordering

Sometimes, it might be necessary to redefine the order in which JAR files are scanned for classes in order to resolve collisions between class names. In these cases, loading priority can be granted to specific JAR files by adding a <class-loader-config> element containing <priority-specifier> elements in the appengine-web.xml file. For example:

<class-loader-config>
  <priority-specifier filename="mailapi.jar"/>
</class-loader-config>

This places "mailapi.jar" as the first JAR file to be searched for classes, barring those in the directory war/WEB-INF/classes/.

If multiple JAR files are prioritized, their original loading order (with respect to each other) will be used. In other words, the order of the <priority-specifier> elements themselves does not matter.

Threads

With the Java 8 runtime, you can create threads using App Engine's ThreadManager API and Java's built-in APIs, for example new Thread(). Currently, if you want to call App Engine APIs (com.google.appengine.api.*), you must call those APIs from a request thread or from a thread created using the ThreadManager API.

An application can

If you create a ThreadPoolExecutor with currentRequestThreadFactory() then shutdown() must be explicitly called before the servlet request completes. Failing to do so will cause the request to not complete and the app server to eventually fail. Note that some libraries may create ThreadPoolExecutors for you.

An application can perform operations against the current thread, such as thread.interrupt().

Each request is limited to 50 concurrent App Engine API request threads.

When using threads, use high level concurrency objects, such as Executor and Runnable. Those take care of many of the subtle but important details of concurrency like Interrupts and scheduling and bookkeeping.

The maximum number of concurrent background threads created by the App Engine API is 10 per instance. (This limit doesn't apply to regular Java threads unrelated to the App Engine API.)

Tools

Supported IDEs

Cloud Tools for Eclipse adds new project wizards and debug configurations to your Eclipse IDE for App Engine projects. You can deploy your App Engine projects live to production from inside Eclipse.

Cloud Tools for IntelliJ enables you to run and debug App Engine applications inside IntelliJ IDEA. You can deploy your App Engine projects live to production without leaving the IDE.

Supported build tools

To speed up your development process, you can use the App Engine plugins for Apache Maven or Gradle:

Local development server

The development server runs your application on your local computer for development and testing. The server simulates the Datastore services. The development server can also generate configuration for Datastore indexes based on the queries the app performs during testing.

Concurrency and latency

Your application's latency has the biggest impact on the number of instances needed to serve your traffic. If you process requests quickly, a single instance can handle a lot of requests.

Single-threaded instances can handle one concurrent request. Therefore, there is a direct relationship between the latency and number of requests that can be handled on the instance per second. For example, 10ms latency equals 100 request/second/instance.

Multi-threaded instances can handle many concurrent requests. Therefore, there is a direct relationship between the CPU consumed and the number of requests/second.

Java apps support concurrent requests, so a single instance can handle new requests while waiting for other requests to complete. Concurrency significantly reduces the number of instances your app requires, but you need to design your app for multithreading.

For example, if a B4 instance (approx 2.4GHz) consumes 10 Mcycles/request, you can process 240 requests/second/instance. If it consumes 100 Mcycles/request, you can process 24 requests/second/instance. These numbers are the ideal case but are fairly realistic in terms of what you can accomplish on an instance.

App Engine Java releases

All released artifacts that start with version 2.x.x use the open source release mechanism. Released artifacts that start with version 1.9.9xx or earlier use the internal build system. See the Github repository for more details.

Environment variables

The following environment variables are set by the runtime:

Environment variable Description
GAE_APPLICATION The ID of your App Engine application. This ID is prefixed with 'region code~' such as 'e~' for applications deployed in Europe.
GAE_DEPLOYMENT_ID The ID of the current deployment.
GAE_ENV The App Engine environment. Set to standard.
GAE_INSTANCE The ID of the instance on which your service is currently running.
GAE_RUNTIME The runtime specified in your app.yaml file.
GAE_SERVICE The service name specified in your app.yaml file. If no service name is specified, it is set to default.
GAE_VERSION The current version label of your service.
GOOGLE_CLOUD_PROJECT The Google Cloud project ID associated with your application.
PORT The port that receives HTTP requests.

You can define additional environment variables in your app.yaml file, but the above values cannot be overridden.