[
https://issues.apache.org/jira/browse/POOL-326?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16027856#comment-16027856
]
Phil Steitz commented on POOL-326:
----------------------------------
Nice job on the test case and bug report, Chris!
Looks like you are using git head, right, Gary? I have also verified that the
problem exists with both the 2.4.2 release jar and git head as of
fc68e1ba783b49df82e27fc88f4cb8819aa0b0c0.
I am not sure, but I suspect at least the borrowObject NPE might be caused by
the following scenario (line numbers from git head)
1. Thread 1 enters deregister and the conditions are met so it progresses to
line 1178 where it waits for a write lock.
2. Thread 2 enters deregister and decrements numInterested, now to -1.
3. Thread 3 (a borrower) enters and exits register, but numInterested just gets
incremented back to 0.
4. Thread 1 completes (second test succeeding), killing the deque.
5. Thread 3 enters deregister and gets NPE
I added some instrumentation to the test code and it looks like the npe on
borrow-deregister is occurring when the pool is out of capacity and numActive
and numIdle for the key under which the borrow request is made are both 0.
Strictly speaking, you can't really tell from instrumentation because between
the exception and the catch other threads could be changing those stats. I get
the same thing repeatedly, though.
When I modify deregister to work like register does - immediately acquire a
read lock and then escalate if needed to a write lock - the test code does not
raise NPEs or ISEs. Attached is a patch with that change. It should be
carefully reviewed and performance-tested before being applied. I doubt the
performance hit would be measurable, but it is adding some lock contention.
> Threading issue, NullPointerException and IllegalStateException in
> GenericKeyedObjectPool
> -----------------------------------------------------------------------------------------
>
> Key: POOL-326
> URL: https://issues.apache.org/jira/browse/POOL-326
> Project: Commons Pool
> Issue Type: Bug
> Affects Versions: 2.4.2
> Reporter: Chris Allison
> Attachments: ObjectPoolIssue.java
>
>
> I'll included a test to help reproduce this issue. Take a look at the
> embedded comments as it's extremely difficult to reproduce. I've seen the
> provided test show the failure on more than one PC so I believe it will show
> the problem.
> Example stack trace for error on return:
> java.util.concurrent.ExecutionException: java.lang.NullPointerException
> at java.util.concurrent.FutureTask.report(FutureTask.java:122)
> at java.util.concurrent.FutureTask.get(FutureTask.java:192)
> at threading_pool.ObjectPoolIssue.run(ObjectPoolIssue.java:63)
> at threading_pool.ObjectPoolIssue.main(ObjectPoolIssue.java:23)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
> Caused by: java.lang.NullPointerException
> at
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.returnObject(GenericKeyedObjectPool.java:474)
> at threading_pool.ObjectPoolIssue$Task.call(ObjectPoolIssue.java:112)
> at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at java.lang.Thread.run(Thread.java:745)
> Example stack trace for error on borrow:
> java.util.concurrent.ExecutionException: java.lang.NullPointerException
> at java.util.concurrent.FutureTask.report(FutureTask.java:122)
> at java.util.concurrent.FutureTask.get(FutureTask.java:192)
> at threading_pool.ObjectPoolIssue.run(ObjectPoolIssue.java:63)
> at threading_pool.ObjectPoolIssue.main(ObjectPoolIssue.java:23)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
> Caused by: java.lang.NullPointerException
> at
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.deregister(GenericKeyedObjectPool.java:1146)
> at
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:438)
> at
> org.apache.commons.pool2.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:279)
> at threading_pool.ObjectPoolIssue$Task.call(ObjectPoolIssue.java:108)
> at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> at
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at java.lang.Thread.run(Thread.java:745)
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)