puniverse / quasar

Fibers, Channels and Actors for the JVM
http://docs.paralleluniverse.co/quasar/
Other
4.56k stars 574 forks source link

JDK8 ThreadLocalRandom throws NPE #244

Closed calvin1978 closed 7 years ago

calvin1978 commented 7 years ago

ThreadLocalRandom in JDK7 is just a Random in thread local, it is ok.

but ThreadLocalRandom in JDK8, use UNSAFE API, and throw NPE now

JDK8 code:

public static ThreadLocalRandom current() { if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0) localInit(); return instance; }

pron commented 7 years ago

How is this issue related to Quasar?

calvin1978 commented 7 years ago

hi @pron , when we use Quasar and use ThreadLocalRandom in JDK8, NPE is thrown

pron commented 7 years ago

I'm sorry, I still don't understand. When does this happen? When running in a fiber? What is the stack trace? Can you provide an example that reproduces this error?

calvin1978 commented 7 years ago

hi @pron ,i found that it the Null Point problem doesn't relate to ThreadLocalRandom, and i can't found the root cause now.

Here is the code , and the NPE is throw on line of "Fiber.park(this);", can you give me some suggestion?

public class FiberFuture<T> implements MyFuture<T> { @Override @Suspendable public T get() throws Exception { try { while (!completed) { Fiber.park(this); } } catch (SuspendExecution e) { //NOSONAR // } catch (Exception e) { throw new IllegalStateException( "The Fiber is not configuration correctly, does @Suspendable enough?, can't get the Fiber instance here. Plese add the -Dco.paralleluniverse.fibers.verifyInstrumentation=true and check the output", e); } ..... }

pron commented 7 years ago

Hi. First of all, Fiber already implements Future, and there are plenty of other synchronization primitives to choose from, so it is recommended that you not implement your own synchronization primitives using park.

Now, the reason for the NPE is a problem with the instrumentation. Try running your code with -Dco.paralleluniverse.fibers.verifyInstrumentation=true on the command line. I suspect that the problem is as follows: you are implementing the interface MyFuture and overriding the get method. But an interface method that has any suspendable overrides must be annotated as well. I.e. MyFuture.get() must also be annotated. Again, it is recommended that you use the existing synchronization primitives that do this correctly.

calvin1978 commented 7 years ago

thanks pron, i found out that another method in chain doesn't mark as @Suspendable.

But it is very strange that why "catch(Exception e){.....}" can't catch this NullPointException?

BTW. The code is just a example, so name it as MyFuture. In fact that it is our Callback interface.