diff options
author | Kun Zhang <zhangkun83@users.noreply.github.com> | 2017-07-06 13:55:44 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-06 13:55:44 -0700 |
commit | 2f6e2c87ab1aeda591fcb7764a8ad6bb20855a2a (patch) | |
tree | 328b7524b6e8b16cd46072aa1681e19553311c2e /context | |
parent | 7c60510794ddd2424d4363f6a057b95020939512 (diff) | |
download | grpc-grpc-java-2f6e2c87ab1aeda591fcb7764a8ad6bb20855a2a.tar.gz |
context: stop using logger at all in static initialization. (#3191)
Turns out avoiding log() alone in the static initialization is not
enough. isLoggable() can also be overridden and call back to Context.
We take a another approach, save the exception and log it outside of
the initialization block.
Diffstat (limited to 'context')
-rw-r--r-- | context/src/main/java/io/grpc/Context.java | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/context/src/main/java/io/grpc/Context.java b/context/src/main/java/io/grpc/Context.java index 41c7c76d7..68228fd85 100644 --- a/context/src/main/java/io/grpc/Context.java +++ b/context/src/main/java/io/grpc/Context.java @@ -19,6 +19,7 @@ package io.grpc; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -110,6 +111,8 @@ public class Context { // One and only one of them is non-null private static final Storage storage; + private static final LinkedBlockingQueue<ClassNotFoundException> storageOverrideNotFoundErrors = + new LinkedBlockingQueue<ClassNotFoundException>(); private static final Exception storageInitError; static { @@ -119,14 +122,10 @@ public class Context { Class<?> clazz = Class.forName("io.grpc.override.ContextStorageOverride"); newStorage = (Storage) clazz.getConstructor().newInstance(); } catch (ClassNotFoundException e) { - if (log.isLoggable(Level.FINE)) { - // Avoid writing to logger because custom log handlers may try to use Context, which is - // problemantic (e.g., NullPointerException) because the Context class has not done loading - // at this point. The caveat is that in environments stderr may be disabled, thus this - // message would go nowhere. - System.err.println("io.grpc.Context: Storage override doesn't exist. Using default."); - e.printStackTrace(); - } + // Avoid writing to logger because custom log handlers may try to use Context, which is + // problemantic (e.g., NullPointerException) because the Context class has not done loading + // at this point. + storageOverrideNotFoundErrors.add(e); newStorage = new ThreadLocalContextStorage(); } catch (Exception e) { error = e; @@ -214,6 +213,13 @@ public class Context { canBeCancelled = isCancellable; } + private static void maybeLogStorageOverrideNotFound() { + ClassNotFoundException e; + while ((e = storageOverrideNotFoundErrors.poll()) != null) { + log.log(Level.FINE, "Storage override doesn't exist. Using default.", e); + } + } + /** * Create a new context which is independently cancellable and also cascades cancellation from * its parent. Callers <em>must</em> ensure that either {@link @@ -381,6 +387,7 @@ public class Context { * }}</pre> */ public Context attach() { + maybeLogStorageOverrideNotFound(); Context previous = current(); storage().attach(this); return previous; |