Example #1
0
  /** {@inheritDoc} */
  public <V, T extends Throwable> V call(Callable<V, T> callable)
      throws IOException, T, InterruptedException {
    UserRequest<V, T> request = null;
    try {
      request = new UserRequest<V, T>(this, callable);
      UserResponse<V, T> r = request.call(this);
      return r.retrieve(this, UserRequest.getClassLoader(callable));

      // re-wrap the exception so that we can capture the stack trace of the caller.
    } catch (ClassNotFoundException e) {
      IOException x = new IOException("Remote call on " + name + " failed");
      x.initCause(e);
      throw x;
    } catch (Error e) {
      IOException x = new IOException("Remote call on " + name + " failed");
      x.initCause(e);
      throw x;
    } finally {
      // since this is synchronous operation, when the round trip is over
      // we assume all the exported objects are out of scope.
      // (that is, the operation shouldn't spawn a new thread or altter
      // global state in the remote system.
      if (request != null) request.releaseExports();
    }
  }
Example #2
0
 /**
  * Preloads jar files on the remote side.
  *
  * <p>This is a performance improvement method that can be safely ignored if your goal is just to
  * make things working.
  *
  * <p>Normally, classes are transferred over the network one at a time, on-demand. This design is
  * mainly driven by how Java classloading works &mdash; we can't predict what classes will be
  * necessarily upfront very easily.
  *
  * <p>Classes are loaded only once, so for long-running {@link Channel}, this is normally an
  * acceptable overhead. But sometimes, for example when a channel is short-lived, or when you know
  * that you'll need a majority of classes in certain jar files, then it is more efficient to send
  * a whole jar file over the network upfront and thereby avoiding individual class transfer over
  * the network.
  *
  * <p>That is what this method does. It ensures that a series of jar files are copied to the
  * remote side (AKA "preloading.") Classloading will consult the preloaded jars before performing
  * network transfer of class files.
  *
  * <p><strong>Beware</strong> that this method is not useful in all configurations. If a {@link
  * RemoteClassLoader} has another {@link RemoteClassLoader} as a {@linkplain ClassLoader#getParent
  * parent}, which would be typical, then preloading a JAR in it will not reduce network
  * round-trips: each class load still has to call {@link ClassLoader#loadClass(String, boolean)
  * loadClass} on the parent, which will wind up checking the remote side just to get a negative
  * answer.
  *
  * @param classLoaderRef This parameter is used to identify the remote classloader that will
  *     prefetch the specified jar files. That is, prefetching will ensure that prefetched jars
  *     will kick in when this {@link Callable} object is actually executed remote side.
  *     <p>{@link RemoteClassLoader}s are created wisely, one per local {@link ClassLoader}, so
  *     this parameter doesn't have to be exactly the same {@link Callable} to be executed later
  *     &mdash; it just has to be of the same class.
  * @param classesInJar {@link Class} objects that identify jar files to be preloaded. Jar files
  *     that contain the specified classes will be preloaded into the remote peer. You just need to
  *     specify one class per one jar.
  * @return true if the preloading actually happened. false if all the jars are already preloaded.
  *     This method is implemented in such a way that unnecessary jar file transfer will be
  *     avoided, and the return value will tell you if this optimization kicked in. Under normal
  *     circumstances your program shouldn't depend on this return value. It's just a hint.
  * @throws IOException if the preloading fails.
  */
 public boolean preloadJar(Callable<?, ?> classLoaderRef, Class... classesInJar)
     throws IOException, InterruptedException {
   return preloadJar(UserRequest.getClassLoader(classLoaderRef), classesInJar);
 }