Java Runtime Environment

www.spiroprojects.com


Selecting the Java runtime

App Engine knows to use the Java runtime environment for your application when you use the AppCfg tool from the Java SDK to upload the app.
The App Engine Java API is represented by the appengine-api-*.jar included with the SDK (where * represents the version of the API and the SDK). You select the version of the API your application uses by including this JAR in the application's WEB-INF/lib/ directory. 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 version number. Your application will continue to use the previous version until you replace the JAR with the new version (from a newer SDK) and re-upload the app.

The sandbox

To allow App Engine to distribute requests for applications across multiple web servers, and to prevent one application from interfering with another, the application runs in a restricted "sandbox" environment. In this environment, the application can execute code, store and query data in the App Engine datastore, use the App Engine mail, URL fetch and users services, and examine the user's web request and prepare the response.
An App Engine application cannot:
·         write to the filesystem. Applications must use the App Engine datastore for storing persistent data. Reading from the filesystem is allowed, and all application files uploaded with the application are available.
·         respond slowly. A web request to an application must be handled within a few seconds. Processes that take a very long time to respond are terminated to avoid overloading the web server.
·         make other kinds of system calls.

Threads

A Java application can create a new thread, but there are some restrictions on how to do it. These threads can't "outlive" the request that creates them. (On a backend server, an application can spawn a background thread, a thread that can "outlive" the request that creates it.)
An application can
  • Implement java.lang.Runnable; and
  • Create a thread factory by calling com.google.appengine.api.ThreadManager.currentRequestThreadFactory()
  • call the factory's newRequestThread method, passing in the Runnable, newRequestThread(runnable)
or use the factory object returned by com.google.appengine.api.ThreadManager.currentRequestThreadFactory() with an ExecutorService (e.g., call Executors.newCachedThreadPool(factory)).
However, you must use one of the methods on ThreadManager to create your threads. You cannot invoke new Thread() yourself or use the default thread factory.
An application can perform operations against the current thread, such as thread.interrupt().
Each request is limited to 50 concurrent request threads. The Java runtime will throw a java.lang.IllegalStateException if you try to create more than 50 threads in a single request.
Caution: Threads are a powerful feature that are full of surprises. If you aren't comfortable with using threads with Java, we recommend Goetz, Java Concurrency in Practice.

The Filesystem

A Java application cannot use any classes used to write to the filesystem, such as java.io.FileWriter. An application can read its own files from the filesystem using classes such as java.io.FileReader. An application can also access its own files as "resources", such as with Class.getResource() or ServletContext.getResource().
Only files that are considered "resource files" are accessible to the application via the filesystem. By default, all files in the WAR are "resource files." You can exclude files from this set using the appengine-web.xml file.

java.lang.System

Features of the java.lang.System class that do not apply to App Engine are disabled.
The following System methods do nothing in App Engine: exit(), gc(), runFinalization(), runFinalizersOnExit()
The following System methods return null: inheritedChannel(), console()
An app cannot provide or directly invoke any native JNI code. The following System methods raise a java.lang.SecurityException: load(), loadLibrary(), setSecurityManager()

Reflection

An application is allowed full, unrestricted, reflective access to its own classes.
It may query any private members, call the method java.lang.reflect.AccessibleObject.setAccessible(), and read/set private members.
An application can also reflect on JRE and API classes, such as java.lang.String and javax.servlet.http.HttpServletRequest. However, it can only access public members of these classes, not protected or private.
An application cannot reflect against any other classes not belonging to itself, and it can not use the setAccessible() method to circumvent these restrictions.

Custom class loading

Custom class loading is fully supported under App Engine. An application is allowed to define its own subclass of ClassLoader that implements application-specific class loading logic. Please be aware, though, that App Engine overrides all ClassLoaders to assign the same permissions to all classes loaded by your application. If you perform custom class loading, be cautious when loading untrusted third-party code.

Class loader JAR ordering

Sometimes, it may 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.

The JRE white list

Access to the classes in the Java standard library (the Java Runtime Environment, or JRE) is limited to the classes in the App Engine JRE White List.

No signed JAR files

App Engine's precompilation isn't compatible with signed JAR files. If your application is precompiled (the default), it can't load signed JAR files. If the application tries to load a signed JAR, at runtime App Engine will generate an exception like
java.lang.SecurityException: SHA1 digest error for com/example/SomeClass.class
    at com.google.appengine.runtime.Request.process-d36f818a24b8cf1d(Request.java)
    at sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:210)
    at java.util.jar.JarVerifier.processEntry(JarVerifier.java:218)
    at java.util.jar.JarVerifier.update(JarVerifier.java:205)
    at java.util.jar.JarVerifier$VerifierStream.read(JarVerifier.java:428)
    at sun.misc.Resource.getBytes(Resource.java:124)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:273)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)

There are two ways to work around this:

The Java SDK and tools

The App Engine Java SDK includes tools for testing your application, uploading your application files, and downloading log data. The SDK also includes a component for Apache Ant to simplify tasks common to App Engine projects. The Google Plugin for Eclipse adds features to the Eclipse IDE for App Engine development, testing and deployment, and includes the complete App Engine SDK. The Eclipse plugin also makes it easy to develop Google Web Toolkit applications and run them on App Engine.
The App Engine Java SDK also has a plugin for supporting development with Apache Maven.
The development server runs your application on your local computer for development and testing. The server simulates the App Engine datastore, services and sandbox restrictions. The development server can also generate configuration for datastore indexes based on the queries the app performs during testing.
A multipurpose tool called AppCfg  handles all command-line interaction with your application running on App Engine. AppCfg can upload your application to App Engine, or just update the datastore index configuration so you can build new indexes before updating the code. It can also download the app's log data, so you can analyze your app's performance using your own tools.

 

Previous
Next Post »