From ceaab7015334653f1cbcce58411416ec4450b763 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 21 Aug 2014 06:31:56 +0200 Subject: [PATCH] [#2800] Fix NPE in SingleThreadEventExecutor on Android Motivation: The recent changes f8bee2e94c33f167bcdefe3e8bbf95e99765032e to use a FJP introduced a regression on Android that cause a NPE. Modifications: - Use AtomicReferenceFieldUpdater so it works also on Android - Fix inspection warnings Result: Netty works again on Android too. --- .../concurrent/SingleThreadEventExecutor.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java index b81b169665..4a6952ce72 100644 --- a/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java +++ b/common/src/main/java/io/netty/util/concurrent/SingleThreadEventExecutor.java @@ -37,6 +37,7 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; /** * Abstract base class for {@link EventExecutor}'s that execute all its submitted tasks in a single thread. @@ -61,8 +62,7 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { }; private static final AtomicIntegerFieldUpdater STATE_UPDATER; - - private static final long threadOffset; + private static final AtomicReferenceFieldUpdater THREAD_UPDATER; static { AtomicIntegerFieldUpdater updater = @@ -72,12 +72,13 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { } STATE_UPDATER = updater; - try { - threadOffset = - PlatformDependent.objectFieldOffset(SingleThreadEventExecutor.class.getDeclaredField("thread")); - } catch (NoSuchFieldException e) { - throw new RuntimeException(); + AtomicReferenceFieldUpdater refUpdater = + PlatformDependent.newAtomicReferenceFieldUpdater(SingleThreadEventExecutor.class, "thread"); + if (refUpdater == null) { + refUpdater = AtomicReferenceFieldUpdater.newUpdater( + SingleThreadEventExecutor.class, Thread.class, "thread"); } + THREAD_UPDATER = refUpdater; } private final Queue taskQueue; @@ -103,7 +104,7 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { private boolean firstRun = true; - private final Runnable AS_RUNNABLE = new Runnable() { + private final Runnable asRunnable = new Runnable() { @Override public void run() { updateThread(Thread.currentThread()); @@ -877,11 +878,11 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { protected final void scheduleExecution() { updateThread(null); - executor.execute(AS_RUNNABLE); + executor.execute(asRunnable); } private void updateThread(Thread t) { - PlatformDependent.putOrderedObject(this, threadOffset, t); + THREAD_UPDATER.lazySet(this, t); } private final class PurgeTask implements Runnable { @@ -911,7 +912,7 @@ public abstract class SingleThreadEventExecutor extends AbstractEventExecutor { } @Override - public Callable unwrap() { + public Callable unwrap() { return null; }