Introduce listenablefuture and failureaccess artifacts, plus InternalFutureFailureAccess.

(taken over from CL 210155310 to add Maven setup)

It provides a direct access to the cause of any failures,
so we can avoid unnecessary allocation of an exception.

Design discussion: https://docs.google.com/document/d/1_RVTtztq5pqrhs0srvJWHMI7PT1tA71--iaauV2l5UA/edit

RELNOTES=Created separate `listenablefuture` and `failureaccess` artifacts, the latter containing the new `InternalFutureFailureAccess`. For more details about `listenablefuture`, see [this announcement](https://groups.google.com/d/topic/guava-announce/Km82fZG68Sw).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212516713
diff --git a/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java b/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
index 380f69f..6c921b5 100644
--- a/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
+++ b/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import java.lang.reflect.Method;
 import java.net.URLClassLoader;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,6 +35,8 @@
 
   private ClassLoader oldClassLoader;
   private URLClassLoader classReloader;
+  private Class<?> settableFutureClass;
+  private Class<?> abstractFutureClass;
 
   @Override
   protected void setUp() throws Exception {
@@ -68,6 +71,8 @@
         };
     oldClassLoader = Thread.currentThread().getContextClassLoader();
     Thread.currentThread().setContextClassLoader(classReloader);
+    abstractFutureClass = classReloader.loadClass(AbstractFuture.class.getName());
+    settableFutureClass = classReloader.loadClass(SettableFuture.class.getName());
   }
 
   @Override
@@ -82,6 +87,7 @@
     assertTrue(future.cancel(false));
     assertTrue(future.isCancelled());
     assertTrue(future.isDone());
+    assertNull(tryInternalFastPathGetFailure(future));
     try {
       future.get();
       fail("Expected CancellationException");
@@ -95,6 +101,7 @@
     assertTrue(future.cancel(true));
     assertTrue(future.isCancelled());
     assertTrue(future.isDone());
+    assertNull(tryInternalFastPathGetFailure(future));
     try {
       future.get();
       fail("Expected CancellationException");
@@ -153,7 +160,13 @@
   }
 
   private Future<?> newFutureInstance() throws Exception {
-    return (Future<?>)
-        classReloader.loadClass(SettableFuture.class.getName()).getMethod("create").invoke(null);
+    return (Future<?>) settableFutureClass.getMethod("create").invoke(null);
+  }
+
+  private Throwable tryInternalFastPathGetFailure(Future<?> future) throws Exception {
+    Method tryInternalFastPathGetFailureMethod =
+        abstractFutureClass.getDeclaredMethod("tryInternalFastPathGetFailure");
+    tryInternalFastPathGetFailureMethod.setAccessible(true);
+    return (Throwable) tryInternalFastPathGetFailureMethod.invoke(future);
   }
 }
diff --git a/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java b/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
index c850032..2bdbef3 100644
--- a/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
+++ b/android/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Range;
 import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.internal.InternalFutureFailureAccess;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -971,6 +972,113 @@
     t.join();
   }
 
+  public void testTrustedGetFailure_Completed() {
+    SettableFuture<String> future = SettableFuture.create();
+    future.set("261");
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testTrustedGetFailure_Failed() {
+    SettableFuture<String> future = SettableFuture.create();
+    Throwable failure = new Throwable();
+    future.setException(failure);
+    assertThat(future.tryInternalFastPathGetFailure()).isEqualTo(failure);
+  }
+
+  public void testTrustedGetFailure_NotCompleted() {
+    SettableFuture<String> future = SettableFuture.create();
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testTrustedGetFailure_CanceledNoCause() {
+    SettableFuture<String> future = SettableFuture.create();
+    future.cancel(false);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_Completed() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    future.set("261");
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_Failed() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    final Throwable failure = new Throwable();
+    future.setException(failure);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_NotCompleted() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_CanceledNoCause() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    future.cancel(false);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testForwardExceptionFastPath() throws Exception {
+    class FailFuture extends InternalFutureFailureAccess implements ListenableFuture<String> {
+      Throwable failure;
+
+      FailFuture(Throwable throwable) {
+        failure = throwable;
+      }
+
+      @Override
+      public boolean cancel(boolean mayInterruptIfRunning) {
+        throw new AssertionFailedError("cancel shouldn't be called on this object");
+      }
+
+      @Override
+      public boolean isCancelled() {
+        return false;
+      }
+
+      @Override
+      public boolean isDone() {
+        return true;
+      }
+
+      @Override
+      public String get() throws InterruptedException, ExecutionException {
+        throw new AssertionFailedError("get() shouldn't be called on this object");
+      }
+
+      @Override
+      public String get(long timeout, TimeUnit unit)
+          throws InterruptedException, ExecutionException, TimeoutException {
+        return get();
+      }
+
+      @Override
+      protected Throwable tryInternalFastPathGetFailure() {
+        return failure;
+      }
+
+      @Override
+      public void addListener(Runnable listener, Executor executor) {
+        throw new AssertionFailedError("addListener() shouldn't be called on this object");
+      }
+    }
+
+    final RuntimeException exception = new RuntimeException("you still didn't say the magic word!");
+    SettableFuture<String> normalFuture = SettableFuture.create();
+    normalFuture.setFuture(new FailFuture(exception));
+    assertTrue(normalFuture.isDone());
+    try {
+      normalFuture.get();
+      fail();
+    } catch (ExecutionException e) {
+      assertSame(exception, e.getCause());
+    }
+  }
+
   private static void awaitUnchecked(final CyclicBarrier barrier) {
     try {
       barrier.await();
diff --git a/android/guava/pom.xml b/android/guava/pom.xml
index f014878..f4dcddb 100644
--- a/android/guava/pom.xml
+++ b/android/guava/pom.xml
@@ -17,6 +17,16 @@
   </description>
   <dependencies>
     <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>failureaccess</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>listenablefuture</artifactId>
+      <version>9999.0-empty-to-avoid-conflict-with-guava</version>
+    </dependency>
+    <dependency>
       <groupId>com.google.code.findbugs</groupId>
       <artifactId>jsr305</artifactId>
     </dependency>
diff --git a/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java
index 564888b..740c58d 100644
--- a/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java
+++ b/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java
@@ -20,6 +20,8 @@
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.internal.InternalFutureFailureAccess;
+import com.google.common.util.concurrent.internal.InternalFutures;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.ForOverride;
 import com.google.j2objc.annotations.ReflectionSupport;
@@ -62,7 +64,8 @@
 @SuppressWarnings("ShortCircuitBoolean") // we use non-short circuiting comparisons intentionally
 @GwtCompatible(emulated = true)
 @ReflectionSupport(value = ReflectionSupport.Level.FULL)
-public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+public abstract class AbstractFuture<V> extends InternalFutureFailureAccess
+    implements ListenableFuture<V> {
   // NOTE: Whenever both tests are cheap and functional, it's faster to use &, | instead of &&, ||
 
   private static final boolean GENERATE_CANCELLATION_CAUSES =
@@ -847,6 +850,13 @@
       }
       return v;
     }
+    if (future instanceof InternalFutureFailureAccess) {
+      Throwable throwable =
+          InternalFutures.tryInternalFastPathGetFailure((InternalFutureFailureAccess) future);
+      if (throwable != null) {
+        return new Failure(throwable);
+      }
+    }
     boolean wasCancelled = future.isCancelled();
     // Don't allocate a CancellationException if it's not necessary
     if (!GENERATE_CANCELLATION_CAUSES & wasCancelled) {
@@ -967,6 +977,39 @@
   @ForOverride
   protected void afterDone() {}
 
+  // TODO(b/114236866): Inherit doc from InternalFutureFailureAccess. Also, -link to its URL.
+  /**
+   * Usually returns {@code null} but, if this {@code Future} has failed, may <i>optionally</i>
+   * return the cause of the failure. "Failure" means specifically "completed with an exception"; it
+   * does not include "was cancelled." To be explicit: If this method returns a non-null value,
+   * then:
+   *
+   * <ul>
+   *   <li>{@code isDone()} must return {@code true}
+   *   <li>{@code isCancelled()} must return {@code false}
+   *   <li>{@code get()} must not block, and it must throw an {@code ExecutionException} with the
+   *       return value of this method as its cause
+   * </ul>
+   *
+   * <p>This method is {@code protected} so that classes like {@code
+   * com.google.common.util.concurrent.SettableFuture} do not expose it to their users as an
+   * instance method. In the unlikely event that you need to call this method, call {@link
+   * InternalFutures#tryInternalFastPathGetFailure(InternalFutureFailureAccess)}.
+   *
+   * @since 27.0
+   */
+  @Override
+  @NullableDecl
+  protected final Throwable tryInternalFastPathGetFailure() {
+    if (this instanceof Trusted) {
+      Object obj = value;
+      if (obj instanceof Failure) {
+        return ((Failure) obj).exception;
+      }
+    }
+    return null;
+  }
+
   /**
    * Returns the exception that this {@code Future} completed with. This includes completion through
    * a call to {@link #setException} or {@link #setFuture setFuture}{@code (failedFuture)} but not
diff --git a/android/guava/src/com/google/common/util/concurrent/ListenableFuture.java b/android/guava/src/com/google/common/util/concurrent/ListenableFuture.java
index 5c56973..33b56d6 100644
--- a/android/guava/src/com/google/common/util/concurrent/ListenableFuture.java
+++ b/android/guava/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -14,7 +14,6 @@
 
 package com.google.common.util.concurrent;
 
-import com.google.common.annotations.GwtCompatible;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
@@ -29,6 +28,8 @@
  * href="https://github.com/google/guava/wiki/ListenableFutureExplained">{@code
  * ListenableFuture}</a>.
  *
+ * <p>This class is GWT-compatible.
+ *
  * <h3>Purpose</h3>
  *
  * <p>The main purpose of {@code ListenableFuture} is to help you chain together a graph of
@@ -97,7 +98,6 @@
  * @author Nishant Thakkar
  * @since 1.0
  */
-@GwtCompatible
 public interface ListenableFuture<V> extends Future<V> {
   /**
    * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on the given executor.
diff --git a/futures/README.md b/futures/README.md
new file mode 100644
index 0000000..7430ebd
--- /dev/null
+++ b/futures/README.md
@@ -0,0 +1,2 @@
+The modules under this directory will be released exactly once each. Once that
+happens, there will be no need to ever update any files here.
diff --git a/futures/failureaccess/pom.xml b/futures/failureaccess/pom.xml
new file mode 100644
index 0000000..01ce092
--- /dev/null
+++ b/futures/failureaccess/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.guava</groupId>
+    <artifactId>guava-parent</artifactId>
+    <version>26.0-android</version>
+  </parent>
+  <artifactId>failureaccess</artifactId>
+  <version>1.0</version>
+  <name>Guava InternalFutureFailureAccess and InternalFutures</name>
+  <description>
+    Contains
+    com.google.common.util.concurrent.internal.InternalFutureFailureAccess and
+    InternalFutures. Most users will never need to use this artifact. Its
+    classes is conceptually a part of Guava, but they're in this separate
+    artifact so that Android libraries can use them without pulling in all of
+    Guava (just as they can use ListenableFuture by depending on the
+    listenablefuture artifact).
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-docs</id>
+          </execution>
+          <execution>
+            <id>generate-javadoc-site-report</id>
+            <phase>site</phase>
+            <goals><goal>javadoc</goal></goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutureFailureAccess.java b/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutureFailureAccess.java
new file mode 100644
index 0000000..7cc8489
--- /dev/null
+++ b/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutureFailureAccess.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent.internal;
+
+/**
+ * A future that, if it fails, may <i>optionally</i> provide access to the cause of the failure.
+ *
+ * <p>This class is used only for micro-optimization. Standard {@code Future} utilities benefit from
+ * this optimization, so there is no need to specialize methods to return or accept this type
+ * instead of {@code ListenableFuture}.
+ *
+ * <p>This class is GWT-compatible.
+ *
+ * @since {@code com.google.guava:failureaccess:1.0}, which was added as a dependency of Guava in
+ *     Guava 27.0
+ */
+public abstract class InternalFutureFailureAccess {
+  /** Constructor for use by subclasses. */
+  protected InternalFutureFailureAccess() {}
+
+  /**
+   * Usually returns {@code null} but, if this {@code Future} has failed, may <i>optionally</i>
+   * return the cause of the failure. "Failure" means specifically "completed with an exception"; it
+   * does not include "was cancelled." To be explicit: If this method returns a non-null value,
+   * then:
+   *
+   * <ul>
+   *   <li>{@code isDone()} must return {@code true}
+   *   <li>{@code isCancelled()} must return {@code false}
+   *   <li>{@code get()} must not block, and it must throw an {@code ExecutionException} with the
+   *       return value of this method as its cause
+   * </ul>
+   *
+   * <p>This method is {@code protected} so that classes like {@code
+   * com.google.common.util.concurrent.SettableFuture} do not expose it to their users as an
+   * instance method. In the unlikely event that you need to call this method, call {@link
+   * InternalFutures#tryInternalFastPathGetFailure(InternalFutureFailureAccess)}.
+   */
+  protected abstract Throwable tryInternalFastPathGetFailure();
+}
diff --git a/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutures.java b/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutures.java
new file mode 100644
index 0000000..42df5ec
--- /dev/null
+++ b/futures/failureaccess/src/com/google/common/util/concurrent/internal/InternalFutures.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent.internal;
+
+/**
+ * Static utilities for {@link InternalFutureFailureAccess}. Most users will never need to use this
+ * class.
+ *
+ * <p>This class is GWT-compatible.
+ *
+ * @since {@code com.google.guava:failureaccess:1.0}, which was added as a dependency of Guava in
+ *     Guava 27.0
+ */
+public final class InternalFutures {
+  /**
+   * Usually returns {@code null} but, if the given {@code Future} has failed, may <i>optionally</i>
+   * return the cause of the failure. "Failure" means specifically "completed with an exception"; it
+   * does not include "was cancelled." To be explicit: If this method returns a non-null value,
+   * then:
+   *
+   * <ul>
+   *   <li>{@code isDone()} must return {@code true}
+   *   <li>{@code isCancelled()} must return {@code false}
+   *   <li>{@code get()} must not block, and it must throw an {@code ExecutionException} with the
+   *       return value of this method as its cause
+   * </ul>
+   */
+  public static Throwable tryInternalFastPathGetFailure(InternalFutureFailureAccess future) {
+    return future.tryInternalFastPathGetFailure();
+  }
+
+  private InternalFutures() {}
+}
diff --git a/futures/listenablefuture1/pom.xml b/futures/listenablefuture1/pom.xml
new file mode 100644
index 0000000..3bd8c01
--- /dev/null
+++ b/futures/listenablefuture1/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.guava</groupId>
+    <artifactId>guava-parent</artifactId>
+    <version>26.0-android</version>
+  </parent>
+  <artifactId>listenablefuture</artifactId>
+  <version>1.0</version>
+  <name>Guava ListenableFuture only</name>
+  <description>
+    Contains Guava's com.google.common.util.concurrent.ListenableFuture class,
+    without any of its other classes -- but is also available in a second
+    "version" that omits the class to avoid conflicts with the copy in Guava
+    itself. The idea is:
+
+    - If users want only ListenableFuture, they depend on listenablefuture-1.0.
+
+    - If users want all of Guava, they depend on guava, which, as of Guava
+    27.0, depends on
+    listenablefuture-9999.0-empty-to-avoid-conflict-with-guava. The 9999.0-...
+    version number is enough for some build systems (notably, Gradle) to select
+    that empty artifact over the "real" listenablefuture-1.0 -- avoiding a
+    conflict with the copy of ListenableFuture in guava itself. If users are
+    using an older version of Guava or a build system other than Gradle, they
+    may see class conflicts. If so, they can solve them by manually excluding
+    the listenablefuture artifact or manually forcing their build systems to
+    use 9999.0-....
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-docs</id>
+          </execution>
+          <execution>
+            <id>generate-javadoc-site-report</id>
+            <phase>site</phase>
+            <goals><goal>javadoc</goal></goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/futures/listenablefuture1/src/com/google/common/util/concurrent/ListenableFuture.java b/futures/listenablefuture1/src/com/google/common/util/concurrent/ListenableFuture.java
new file mode 100644
index 0000000..33b56d6
--- /dev/null
+++ b/futures/listenablefuture1/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.common.util.concurrent;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+
+/**
+ * A {@link Future} that accepts completion listeners. Each listener has an associated executor, and
+ * it is invoked using this executor once the future's computation is {@linkplain Future#isDone()
+ * complete}. If the computation has already completed when the listener is added, the listener will
+ * execute immediately.
+ *
+ * <p>See the Guava User Guide article on <a
+ * href="https://github.com/google/guava/wiki/ListenableFutureExplained">{@code
+ * ListenableFuture}</a>.
+ *
+ * <p>This class is GWT-compatible.
+ *
+ * <h3>Purpose</h3>
+ *
+ * <p>The main purpose of {@code ListenableFuture} is to help you chain together a graph of
+ * asynchronous operations. You can chain them together manually with calls to methods like {@link
+ * Futures#transform(ListenableFuture, com.google.common.base.Function, Executor)
+ * Futures.transform}, but you will often find it easier to use a framework. Frameworks automate the
+ * process, often adding features like monitoring, debugging, and cancellation. Examples of
+ * frameworks include:
+ *
+ * <ul>
+ *   <li><a href="http://google.github.io/dagger/producers.html">Dagger Producers</a>
+ * </ul>
+ *
+ * <p>The main purpose of {@link #addListener addListener} is to support this chaining. You will
+ * rarely use it directly, in part because it does not provide direct access to the {@code Future}
+ * result. (If you want such access, you may prefer {@link Futures#addCallback
+ * Futures.addCallback}.) Still, direct {@code addListener} calls are occasionally useful:
+ *
+ * <pre>{@code
+ * final String name = ...;
+ * inFlight.add(name);
+ * ListenableFuture<Result> future = service.query(name);
+ * future.addListener(new Runnable() {
+ *   public void run() {
+ *     processedCount.incrementAndGet();
+ *     inFlight.remove(name);
+ *     lastProcessed.set(name);
+ *     logger.info("Done with {0}", name);
+ *   }
+ * }, executor);
+ * }</pre>
+ *
+ * <h3>How to get an instance</h3>
+ *
+ * <p>We encourage you to return {@code ListenableFuture} from your methods so that your users can
+ * take advantage of the {@linkplain Futures utilities built atop the class}. The way that you will
+ * create {@code ListenableFuture} instances depends on how you currently create {@code Future}
+ * instances:
+ *
+ * <ul>
+ *   <li>If you receive them from an {@code java.util.concurrent.ExecutorService}, convert that
+ *       service to a {@link ListeningExecutorService}, usually by calling {@link
+ *       MoreExecutors#listeningDecorator(java.util.concurrent.ExecutorService)
+ *       MoreExecutors.listeningDecorator}.
+ *   <li>If you manually call {@link java.util.concurrent.FutureTask#set} or a similar method,
+ *       create a {@link SettableFuture} instead. (If your needs are more complex, you may prefer
+ *       {@link AbstractFuture}.)
+ * </ul>
+ *
+ * <p><b>Test doubles</b>: If you need a {@code ListenableFuture} for your test, try a {@link
+ * SettableFuture} or one of the methods in the {@link Futures#immediateFuture Futures.immediate*}
+ * family. <b>Avoid</b> creating a mock or stub {@code Future}. Mock and stub implementations are
+ * fragile because they assume that only certain methods will be called and because they often
+ * implement subtleties of the API improperly.
+ *
+ * <p><b>Custom implementation</b>: Avoid implementing {@code ListenableFuture} from scratch. If you
+ * can't get by with the standard implementations, prefer to derive a new {@code Future} instance
+ * with the methods in {@link Futures} or, if necessary, to extend {@link AbstractFuture}.
+ *
+ * <p>Occasionally, an API will return a plain {@code Future} and it will be impossible to change
+ * the return type. For this case, we provide a more expensive workaround in {@code
+ * JdkFutureAdapters}. However, when possible, it is more efficient and reliable to create a {@code
+ * ListenableFuture} directly.
+ *
+ * @author Sven Mawson
+ * @author Nishant Thakkar
+ * @since 1.0
+ */
+public interface ListenableFuture<V> extends Future<V> {
+  /**
+   * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on the given executor.
+   * The listener will run when the {@code Future}'s computation is {@linkplain Future#isDone()
+   * complete} or, if the computation is already complete, immediately.
+   *
+   * <p>There is no guaranteed ordering of execution of listeners, but any listener added through
+   * this method is guaranteed to be called once the computation is complete.
+   *
+   * <p>Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
+   * during {@code Executor.execute} (e.g., a {@code RejectedExecutionException} or an exception
+   * thrown by {@linkplain MoreExecutors#directExecutor direct execution}) will be caught and
+   * logged.
+   *
+   * <p>Note: For fast, lightweight listeners that would be safe to execute in any thread, consider
+   * {@link MoreExecutors#directExecutor}. Otherwise, avoid it. Heavyweight {@code directExecutor}
+   * listeners can cause problems, and these problems can be difficult to reproduce because they
+   * depend on timing. For example:
+   *
+   * <ul>
+   *   <li>The listener may be executed by the caller of {@code addListener}. That caller may be a
+   *       UI thread or other latency-sensitive thread. This can harm UI responsiveness.
+   *   <li>The listener may be executed by the thread that completes this {@code Future}. That
+   *       thread may be an internal system thread such as an RPC network thread. Blocking that
+   *       thread may stall progress of the whole system. It may even cause a deadlock.
+   *   <li>The listener may delay other listeners, even listeners that are not themselves {@code
+   *       directExecutor} listeners.
+   * </ul>
+   *
+   * <p>This is the most general listener interface. For common operations performed using
+   * listeners, see {@link Futures}. For a simplified but general listener interface, see {@link
+   * Futures#addCallback addCallback()}.
+   *
+   * <p>Memory consistency effects: Actions in a thread prior to adding a listener <a
+   * href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
+   * <i>happen-before</i></a> its execution begins, perhaps in another thread.
+   *
+   * @param listener the listener to run when the computation is complete
+   * @param executor the executor to run the listener in
+   * @throws RejectedExecutionException if we tried to execute the listener immediately but the
+   *     executor rejected it.
+   */
+  void addListener(Runnable listener, Executor executor);
+}
diff --git a/futures/listenablefuture9999/pom.xml b/futures/listenablefuture9999/pom.xml
new file mode 100644
index 0000000..ad3f23e
--- /dev/null
+++ b/futures/listenablefuture9999/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.google.guava</groupId>
+    <artifactId>guava-parent</artifactId>
+    <version>26.0-android</version>
+  </parent>
+  <artifactId>listenablefuture</artifactId>
+  <version>9999.0-empty-to-avoid-conflict-with-guava</version>
+  <name>Guava ListenableFuture only</name>
+  <description>
+    An empty artifact that Guava depends on to signal that it is providing
+    ListenableFuture -- but is also available in a second "version" that
+    contains com.google.common.util.concurrent.ListenableFuture class, without
+    any other Guava classes. The idea is:
+
+    - If users want only ListenableFuture, they depend on listenablefuture-1.0.
+
+    - If users want all of Guava, they depend on guava, which, as of Guava
+    27.0, depends on
+    listenablefuture-9999.0-empty-to-avoid-conflict-with-guava. The 9999.0-...
+    version number is enough for some build systems (notably, Gradle) to select
+    that empty artifact over the "real" listenablefuture-1.0 -- avoiding a
+    conflict with the copy of ListenableFuture in guava itself. If users are
+    using an older version of Guava or a build system other than Gradle, they
+    may see class conflicts. If so, they can solve them by manually excluding
+    the listenablefuture artifact or manually forcing their build systems to
+    use 9999.0-....
+  </description>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-docs</id>
+          </execution>
+          <execution>
+            <id>generate-javadoc-site-report</id>
+            <phase>site</phase>
+            <goals><goal>javadoc</goal></goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/guava-gwt/pom.xml b/guava-gwt/pom.xml
index a20c034..5fa6c42 100644
--- a/guava-gwt/pom.xml
+++ b/guava-gwt/pom.xml
@@ -46,6 +46,11 @@
   <dependencies>
     <dependency>
       <groupId>com.google.guava</groupId>
+      <artifactId>failureaccess</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -125,6 +130,20 @@
         <artifactId>maven-dependency-plugin</artifactId>
         <executions>
           <execution>
+            <id>unpack-failureaccess-sources</id>
+            <phase>generate-resources</phase>
+            <goals><goal>unpack-dependencies</goal></goals>
+            <configuration>
+              <includeArtifactIds>failureaccess</includeArtifactIds>
+              <classifier>sources</classifier>
+              <excludeTransitive>true</excludeTransitive>
+              <excludes>META-INF/MANIFEST.MF</excludes>
+              <outputDirectory>${project.build.directory}/failureaccess-sources</outputDirectory>
+              <type>java-source</type>
+              <silent>false</silent>
+            </configuration>
+          </execution>
+          <execution>
             <id>unpack-guava-sources</id>
             <phase>generate-resources</phase>
             <goals><goal>unpack-dependencies</goal></goals>
@@ -184,6 +203,12 @@
         <dependencies>
           <dependency>
             <groupId>com.google.guava</groupId>
+            <artifactId>failureaccess</artifactId>
+            <version>1.0</version>
+            <classifier>sources</classifier>
+          </dependency>
+          <dependency>
+            <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
             <version>${project.version}</version>
             <classifier>sources</classifier>
@@ -222,6 +247,22 @@
                     <contains text="@GwtCompatible"/>
                   </fileset>
                 </copy>
+                <!-- The following don't contain @GwtCompatible for dependency reasons. -->
+                <copy toDir="${project.build.directory}/guava-gwt-sources">
+                  <fileset dir="${project.build.directory}/guava-sources">
+                    <include name="**/ListenableFuture.java" />
+                  </fileset>
+                </copy>
+                <copy toDir="${project.build.directory}/guava-gwt-sources">
+                  <fileset dir="${project.build.directory}/failureaccess-sources">
+                    <include name="**/InternalFutures.java" />
+                  </fileset>
+                </copy>
+                <copy toDir="${project.build.directory}/guava-gwt-sources">
+                  <fileset dir="${project.build.directory}/failureaccess-sources">
+                    <include name="**/InternalFutureFailureAccess.java" />
+                  </fileset>
+                </copy>
                 <copy toDir="${project.build.directory}/guava-test-gwt-sources">
                   <fileset dir="${project.build.directory}/guava-test-sources">
                     <contains text="@GwtCompatible"/>
diff --git a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
index bc05340..96691b8 100644
--- a/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
+++ b/guava-gwt/src-super/com/google/common/util/concurrent/super/com/google/common/util/concurrent/AbstractFuture.java
@@ -22,6 +22,7 @@
 import static com.google.common.util.concurrent.Futures.getDone;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
 
+import com.google.common.util.concurrent.internal.InternalFutureFailureAccess;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CancellationException;
@@ -35,7 +36,8 @@
 import org.checkerframework.checker.nullness.qual.Nullable;
 
 /** Emulation for AbstractFuture in GWT. */
-public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+public abstract class AbstractFuture<V> extends InternalFutureFailureAccess
+    implements ListenableFuture<V> {
 
   /**
    * Tag interface marking trusted subclasses. This enables some optimizations. The implementation
@@ -215,6 +217,11 @@
 
   protected void afterDone() {}
 
+  @Override
+  protected final Throwable tryInternalFastPathGetFailure() {
+    return state == State.FAILURE ? throwable : null;
+  }
+
   final Throwable trustedGetException() {
     checkState(state == State.FAILURE);
     return throwable;
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
index 380f69f..6c921b5 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureCancellationCauseTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import java.lang.reflect.Method;
 import java.net.URLClassLoader;
 import java.util.HashMap;
 import java.util.Map;
@@ -34,6 +35,8 @@
 
   private ClassLoader oldClassLoader;
   private URLClassLoader classReloader;
+  private Class<?> settableFutureClass;
+  private Class<?> abstractFutureClass;
 
   @Override
   protected void setUp() throws Exception {
@@ -68,6 +71,8 @@
         };
     oldClassLoader = Thread.currentThread().getContextClassLoader();
     Thread.currentThread().setContextClassLoader(classReloader);
+    abstractFutureClass = classReloader.loadClass(AbstractFuture.class.getName());
+    settableFutureClass = classReloader.loadClass(SettableFuture.class.getName());
   }
 
   @Override
@@ -82,6 +87,7 @@
     assertTrue(future.cancel(false));
     assertTrue(future.isCancelled());
     assertTrue(future.isDone());
+    assertNull(tryInternalFastPathGetFailure(future));
     try {
       future.get();
       fail("Expected CancellationException");
@@ -95,6 +101,7 @@
     assertTrue(future.cancel(true));
     assertTrue(future.isCancelled());
     assertTrue(future.isDone());
+    assertNull(tryInternalFastPathGetFailure(future));
     try {
       future.get();
       fail("Expected CancellationException");
@@ -153,7 +160,13 @@
   }
 
   private Future<?> newFutureInstance() throws Exception {
-    return (Future<?>)
-        classReloader.loadClass(SettableFuture.class.getName()).getMethod("create").invoke(null);
+    return (Future<?>) settableFutureClass.getMethod("create").invoke(null);
+  }
+
+  private Throwable tryInternalFastPathGetFailure(Future<?> future) throws Exception {
+    Method tryInternalFastPathGetFailureMethod =
+        abstractFutureClass.getDeclaredMethod("tryInternalFastPathGetFailure");
+    tryInternalFastPathGetFailureMethod.setAccessible(true);
+    return (Throwable) tryInternalFastPathGetFailureMethod.invoke(future);
   }
 }
diff --git a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
index c850032..2bdbef3 100644
--- a/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
+++ b/guava-tests/test/com/google/common/util/concurrent/AbstractFutureTest.java
@@ -22,6 +22,7 @@
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Range;
 import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.internal.InternalFutureFailureAccess;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -971,6 +972,113 @@
     t.join();
   }
 
+  public void testTrustedGetFailure_Completed() {
+    SettableFuture<String> future = SettableFuture.create();
+    future.set("261");
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testTrustedGetFailure_Failed() {
+    SettableFuture<String> future = SettableFuture.create();
+    Throwable failure = new Throwable();
+    future.setException(failure);
+    assertThat(future.tryInternalFastPathGetFailure()).isEqualTo(failure);
+  }
+
+  public void testTrustedGetFailure_NotCompleted() {
+    SettableFuture<String> future = SettableFuture.create();
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testTrustedGetFailure_CanceledNoCause() {
+    SettableFuture<String> future = SettableFuture.create();
+    future.cancel(false);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_Completed() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    future.set("261");
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_Failed() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    final Throwable failure = new Throwable();
+    future.setException(failure);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_NotCompleted() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    assertThat(future.isDone()).isFalse();
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testGetFailure_CanceledNoCause() {
+    AbstractFuture<String> future = new AbstractFuture<String>() {};
+    future.cancel(false);
+    assertThat(future.tryInternalFastPathGetFailure()).isNull();
+  }
+
+  public void testForwardExceptionFastPath() throws Exception {
+    class FailFuture extends InternalFutureFailureAccess implements ListenableFuture<String> {
+      Throwable failure;
+
+      FailFuture(Throwable throwable) {
+        failure = throwable;
+      }
+
+      @Override
+      public boolean cancel(boolean mayInterruptIfRunning) {
+        throw new AssertionFailedError("cancel shouldn't be called on this object");
+      }
+
+      @Override
+      public boolean isCancelled() {
+        return false;
+      }
+
+      @Override
+      public boolean isDone() {
+        return true;
+      }
+
+      @Override
+      public String get() throws InterruptedException, ExecutionException {
+        throw new AssertionFailedError("get() shouldn't be called on this object");
+      }
+
+      @Override
+      public String get(long timeout, TimeUnit unit)
+          throws InterruptedException, ExecutionException, TimeoutException {
+        return get();
+      }
+
+      @Override
+      protected Throwable tryInternalFastPathGetFailure() {
+        return failure;
+      }
+
+      @Override
+      public void addListener(Runnable listener, Executor executor) {
+        throw new AssertionFailedError("addListener() shouldn't be called on this object");
+      }
+    }
+
+    final RuntimeException exception = new RuntimeException("you still didn't say the magic word!");
+    SettableFuture<String> normalFuture = SettableFuture.create();
+    normalFuture.setFuture(new FailFuture(exception));
+    assertTrue(normalFuture.isDone());
+    try {
+      normalFuture.get();
+      fail();
+    } catch (ExecutionException e) {
+      assertSame(exception, e.getCause());
+    }
+  }
+
   private static void awaitUnchecked(final CyclicBarrier barrier) {
     try {
       barrier.await();
diff --git a/guava/pom.xml b/guava/pom.xml
index a637348..ec99618 100644
--- a/guava/pom.xml
+++ b/guava/pom.xml
@@ -17,6 +17,16 @@
   </description>
   <dependencies>
     <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>failureaccess</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>listenablefuture</artifactId>
+      <version>9999.0-empty-to-avoid-conflict-with-guava</version>
+    </dependency>
+    <dependency>
       <groupId>com.google.code.findbugs</groupId>
       <artifactId>jsr305</artifactId>
     </dependency>
diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
index 803ae2b..c867dbf 100644
--- a/guava/src/com/google/common/util/concurrent/AbstractFuture.java
+++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java
@@ -20,6 +20,8 @@
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.GwtCompatible;
+import com.google.common.util.concurrent.internal.InternalFutureFailureAccess;
+import com.google.common.util.concurrent.internal.InternalFutures;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.google.errorprone.annotations.ForOverride;
 import com.google.j2objc.annotations.ReflectionSupport;
@@ -62,7 +64,8 @@
 @SuppressWarnings("ShortCircuitBoolean") // we use non-short circuiting comparisons intentionally
 @GwtCompatible(emulated = true)
 @ReflectionSupport(value = ReflectionSupport.Level.FULL)
-public abstract class AbstractFuture<V> implements ListenableFuture<V> {
+public abstract class AbstractFuture<V> extends InternalFutureFailureAccess
+    implements ListenableFuture<V> {
   // NOTE: Whenever both tests are cheap and functional, it's faster to use &, | instead of &&, ||
 
   private static final boolean GENERATE_CANCELLATION_CAUSES =
@@ -847,6 +850,13 @@
       }
       return v;
     }
+    if (future instanceof InternalFutureFailureAccess) {
+      Throwable throwable =
+          InternalFutures.tryInternalFastPathGetFailure((InternalFutureFailureAccess) future);
+      if (throwable != null) {
+        return new Failure(throwable);
+      }
+    }
     boolean wasCancelled = future.isCancelled();
     // Don't allocate a CancellationException if it's not necessary
     if (!GENERATE_CANCELLATION_CAUSES & wasCancelled) {
@@ -967,6 +977,39 @@
   @ForOverride
   protected void afterDone() {}
 
+  // TODO(b/114236866): Inherit doc from InternalFutureFailureAccess. Also, -link to its URL.
+  /**
+   * Usually returns {@code null} but, if this {@code Future} has failed, may <i>optionally</i>
+   * return the cause of the failure. "Failure" means specifically "completed with an exception"; it
+   * does not include "was cancelled." To be explicit: If this method returns a non-null value,
+   * then:
+   *
+   * <ul>
+   *   <li>{@code isDone()} must return {@code true}
+   *   <li>{@code isCancelled()} must return {@code false}
+   *   <li>{@code get()} must not block, and it must throw an {@code ExecutionException} with the
+   *       return value of this method as its cause
+   * </ul>
+   *
+   * <p>This method is {@code protected} so that classes like {@code
+   * com.google.common.util.concurrent.SettableFuture} do not expose it to their users as an
+   * instance method. In the unlikely event that you need to call this method, call {@link
+   * InternalFutures#tryInternalFastPathGetFailure(InternalFutureFailureAccess)}.
+   *
+   * @since 27.0
+   */
+  @Override
+  @Nullable
+  protected final Throwable tryInternalFastPathGetFailure() {
+    if (this instanceof Trusted) {
+      Object obj = value;
+      if (obj instanceof Failure) {
+        return ((Failure) obj).exception;
+      }
+    }
+    return null;
+  }
+
   /**
    * Returns the exception that this {@code Future} completed with. This includes completion through
    * a call to {@link #setException} or {@link #setFuture setFuture}{@code (failedFuture)} but not
diff --git a/guava/src/com/google/common/util/concurrent/ListenableFuture.java b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
index 5c56973..33b56d6 100644
--- a/guava/src/com/google/common/util/concurrent/ListenableFuture.java
+++ b/guava/src/com/google/common/util/concurrent/ListenableFuture.java
@@ -14,7 +14,6 @@
 
 package com.google.common.util.concurrent;
 
-import com.google.common.annotations.GwtCompatible;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.RejectedExecutionException;
@@ -29,6 +28,8 @@
  * href="https://github.com/google/guava/wiki/ListenableFutureExplained">{@code
  * ListenableFuture}</a>.
  *
+ * <p>This class is GWT-compatible.
+ *
  * <h3>Purpose</h3>
  *
  * <p>The main purpose of {@code ListenableFuture} is to help you chain together a graph of
@@ -97,7 +98,6 @@
  * @author Nishant Thakkar
  * @since 1.0
  */
-@GwtCompatible
 public interface ListenableFuture<V> extends Future<V> {
   /**
    * Registers a listener to be {@linkplain Executor#execute(Runnable) run} on the given executor.