From 0357006a920c9cf84d47901471a525da85deba34 Mon Sep 17 00:00:00 2001 From: cpovirk Date: Thu, 10 Dec 2020 09:03:28 -0800 Subject: [PATCH] Log a warning if running under a Java 7 VM. More precisely, log a warning if lambda expressions or type annotations in our classes would produce an exception. If someone wants to use Retrolambda or a similar tool to rewrite our classes, that's fine with us if it works. And our support for Android is unchanged: The Android toolchain rewrites lambdas and removes type annotations. This is a step toward removing Java 7 support entirely: https://github.com/google/guava/issues/5269 RELNOTES=Introduced a warning log message when running under Java 7. This warning is not _guaranteed_ to be logged when running under Java 7, so please don't rely on it as your only warning about future problems. If the warning _itself_ causes you trouble, you can eliminate it by silencing the logger for `com.google.common.base.MoreObjects$ToStringHelper` (which is used _only_ for this warning). This warning prepares for [removing support for Java 7 in 2021](https://github.com/google/guava/issues/5269). Please report any problems. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=346795766 --- android/guava/pom.xml | 36 +++++++++++++++ .../com/google/common/base/Java8Usage.java | 45 +++++++++++++++++++ .../com/google/common/base/MoreObjects.java | 36 +++++++++++++++ android/pom.xml | 10 +++++ guava/pom.xml | 36 +++++++++++++++ .../com/google/common/base/Java8Usage.java | 45 +++++++++++++++++++ .../com/google/common/base/MoreObjects.java | 36 +++++++++++++++ pom.xml | 10 +++++ 8 files changed, 254 insertions(+) create mode 100644 android/guava/src/com/google/common/base/Java8Usage.java create mode 100644 guava/src/com/google/common/base/Java8Usage.java diff --git a/android/guava/pom.xml b/android/guava/pom.xml index e01a6104fc9a..5deda6e057fc 100644 --- a/android/guava/pom.xml +++ b/android/guava/pom.xml @@ -90,6 +90,42 @@ maven-compiler-plugin + + + + default-compile + compile + + compile + + + + **/Java8Usage.java + + + 8 + 8 + + + + main-compile + compile + + compile + + + + **/Java8Usage.java + + + + maven-source-plugin diff --git a/android/guava/src/com/google/common/base/Java8Usage.java b/android/guava/src/com/google/common/base/Java8Usage.java new file mode 100644 index 000000000000..78130cf676d9 --- /dev/null +++ b/android/guava/src/com/google/common/base/Java8Usage.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 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.base; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; + +/** + * A class that uses a couple Java 8 features but doesn't really do anything. This lets us attempt + * to load it and log a warning if that fails, giving users advance notice of our dropping Java 8 + * support. + */ +/* + * This class should be annotated @GwtCompatible. But if we annotate it @GwtCompatible, then we need + * to build GwtCompatible.java (-source 7 -target 7 in the Android flavor) before we build + * Java8Usage.java (-source 8 target 8, which we already need to build before the rest of + * common.base). We could configure Maven to do that, but it's easier to just skip the annotation. + */ +final class Java8Usage { + @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) + private @interface SomeTypeAnnotation {} + + @CanIgnoreReturnValue + static @SomeTypeAnnotation String performCheck() { + Runnable r = () -> {}; + r.run(); + return ""; + } + + private Java8Usage() {} +} diff --git a/android/guava/src/com/google/common/base/MoreObjects.java b/android/guava/src/com/google/common/base/MoreObjects.java index a56b2a69def0..a8ee412c67e0 100644 --- a/android/guava/src/com/google/common/base/MoreObjects.java +++ b/android/guava/src/com/google/common/base/MoreObjects.java @@ -15,10 +15,13 @@ package com.google.common.base; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.logging.Level.WARNING; import com.google.common.annotations.GwtCompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.Arrays; +import java.util.logging.Logger; import org.checkerframework.checker.nullness.compatqual.NullableDecl; /** @@ -141,6 +144,38 @@ public static ToStringHelper toStringHelper(String className) { * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}). */ public static final class ToStringHelper { + @GuardedBy("ToStringHelper.class") + private static boolean performedJava8CompatibilityCheck; + + private static void java8CompatibilityCheck() { + @SuppressWarnings("GuardedBy") + boolean racyReadForDoubleCheckedLock = performedJava8CompatibilityCheck; + if (racyReadForDoubleCheckedLock) { + return; + } + synchronized (ToStringHelper.class) { + if (performedJava8CompatibilityCheck) { + return; + } + performedJava8CompatibilityCheck = true; + } + + try { + Java8Usage.performCheck(); + } catch (Throwable underlying) { + Exception toLog = + new Exception( + "Guava will drop support for Java 7 in 2021. Please let us know if this will cause" + + " you problems: https://github.com/google/guava/issues/5269", + underlying); + Logger.getLogger(ToStringHelper.class.getName()) + .log( + WARNING, + "Java 7 compatibility warning: See https://github.com/google/guava/issues/5269", + toLog); + } + } + private final String className; private final ValueHolder holderHead = new ValueHolder(); private ValueHolder holderTail = holderHead; @@ -148,6 +183,7 @@ public static final class ToStringHelper { /** Use {@link MoreObjects#toStringHelper(Object)} to create an instance. */ private ToStringHelper(String className) { + java8CompatibilityCheck(); this.className = checkNotNull(className); } diff --git a/android/pom.xml b/android/pom.xml index f1b9fb1e1e5f..c1948fa53724 100644 --- a/android/pom.xml +++ b/android/pom.xml @@ -118,6 +118,16 @@ 1.7 1.7 + + + -sourcepath + doesnotexist + diff --git a/guava/pom.xml b/guava/pom.xml index 4a7cd5c186d1..d95559cbcb48 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -90,6 +90,42 @@ maven-compiler-plugin + + + + default-compile + compile + + compile + + + + **/Java8Usage.java + + + 8 + 8 + + + + main-compile + compile + + compile + + + + **/Java8Usage.java + + + + maven-source-plugin diff --git a/guava/src/com/google/common/base/Java8Usage.java b/guava/src/com/google/common/base/Java8Usage.java new file mode 100644 index 000000000000..78130cf676d9 --- /dev/null +++ b/guava/src/com/google/common/base/Java8Usage.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 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.base; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; + +/** + * A class that uses a couple Java 8 features but doesn't really do anything. This lets us attempt + * to load it and log a warning if that fails, giving users advance notice of our dropping Java 8 + * support. + */ +/* + * This class should be annotated @GwtCompatible. But if we annotate it @GwtCompatible, then we need + * to build GwtCompatible.java (-source 7 -target 7 in the Android flavor) before we build + * Java8Usage.java (-source 8 target 8, which we already need to build before the rest of + * common.base). We could configure Maven to do that, but it's easier to just skip the annotation. + */ +final class Java8Usage { + @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) + @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) + private @interface SomeTypeAnnotation {} + + @CanIgnoreReturnValue + static @SomeTypeAnnotation String performCheck() { + Runnable r = () -> {}; + r.run(); + return ""; + } + + private Java8Usage() {} +} diff --git a/guava/src/com/google/common/base/MoreObjects.java b/guava/src/com/google/common/base/MoreObjects.java index cf901b5954e0..a182829660f2 100644 --- a/guava/src/com/google/common/base/MoreObjects.java +++ b/guava/src/com/google/common/base/MoreObjects.java @@ -15,10 +15,13 @@ package com.google.common.base; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.logging.Level.WARNING; import com.google.common.annotations.GwtCompatible; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.Arrays; +import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.Nullable; /** @@ -141,6 +144,38 @@ public static ToStringHelper toStringHelper(String className) { * @since 18.0 (since 2.0 as {@code Objects.ToStringHelper}). */ public static final class ToStringHelper { + @GuardedBy("ToStringHelper.class") + private static boolean performedJava8CompatibilityCheck; + + private static void java8CompatibilityCheck() { + @SuppressWarnings("GuardedBy") + boolean racyReadForDoubleCheckedLock = performedJava8CompatibilityCheck; + if (racyReadForDoubleCheckedLock) { + return; + } + synchronized (ToStringHelper.class) { + if (performedJava8CompatibilityCheck) { + return; + } + performedJava8CompatibilityCheck = true; + } + + try { + Java8Usage.performCheck(); + } catch (Throwable underlying) { + Exception toLog = + new Exception( + "Guava will drop support for Java 7 in 2021. Please let us know if this will cause" + + " you problems: https://github.com/google/guava/issues/5269", + underlying); + Logger.getLogger(ToStringHelper.class.getName()) + .log( + WARNING, + "Java 7 compatibility warning: See https://github.com/google/guava/issues/5269", + toLog); + } + } + private final String className; private final ValueHolder holderHead = new ValueHolder(); private ValueHolder holderTail = holderHead; @@ -148,6 +183,7 @@ public static final class ToStringHelper { /** Use {@link MoreObjects#toStringHelper(Object)} to create an instance. */ private ToStringHelper(String className) { + java8CompatibilityCheck(); this.className = checkNotNull(className); } diff --git a/pom.xml b/pom.xml index 01ee0f43c76f..22d68ffdf448 100644 --- a/pom.xml +++ b/pom.xml @@ -119,6 +119,16 @@ 1.8 1.8 + + + -sourcepath + doesnotexist +