aboutsummaryrefslogtreecommitdiff
path: root/context
diff options
context:
space:
mode:
authorKun Zhang <zhangkun83@users.noreply.github.com>2017-07-06 13:55:44 -0700
committerGitHub <noreply@github.com>2017-07-06 13:55:44 -0700
commit2f6e2c87ab1aeda591fcb7764a8ad6bb20855a2a (patch)
tree328b7524b6e8b16cd46072aa1681e19553311c2e /context
parent7c60510794ddd2424d4363f6a057b95020939512 (diff)
downloadgrpc-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.java23
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;