FULL PRODUCT VERSION :
java version "1.8.0_51"
Java(TM) SE Runtime Environment (build 1.8.0_51-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.51-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
linux_suse_sles_11 and windows 7-64bit
A DESCRIPTION OF THE PROBLEM :
When spring framework init a bean object, it will invoke afterPropertiesSet() method.
My code like this:
public void afterPropertiesSet()
{
Executors.newSingleThreadExecutor().submit(new Runnable()
{
@Override
public void run()
{
Thread.currentThread().setName("StartUp-1");
try
{
.....
}
catch (Exception e)
{
logger.error("", e);
}
}
});
}
but there throw a RejectedExeception:
Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@694abf75 rejected from java.util.concurrent.ThreadPoolExecutor@15e7578d[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at java.util.concurrent.Executors$DelegatedExecutorService.submit(Executors.java:678)
at demo.MyService.afterPropertiesSet(TopoService.java:248)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 18 more
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I submited this bug at JDK-8144799. But that issue has been closed. This time I find a way to reproducing that issue.
There has possible the ThreadPoolExecutor already finalize by jvm before submit Runnable instance?
I wrote a test case like this:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class A implements Runnable {
public void afterProperties() {
Executors.newSingleThreadExecutor().submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
@Override
public void run() {
afterProperties();
}
public static void main(String[] args) throws Exception {
ExecutorService execMain = Executors.newFixedThreadPool(2);
A testcase = new A();
for (int i = 0; i < 1000; i++) {
execMain.submit(testcase);
}
}
}
The byte code for A.afterProperties:
public void afterProperties();
0 invokestatic java.util.concurrent.Executors.newSingleThreadExecutor() : java.util.concurrent.ExecutorService [17]
3 new A$1 [23]
6 dup
7 aload_0 [this]
8 invokespecial A$1(A) [25]
11 invokeinterface java.util.concurrent.ExecutorService.submit(java.lang.Runnable) : java.util.concurrent.Future [28] [nargs: 2]
16 pop
17 return
Most of the time, I think there have 1001 instance for ThreadPoolWorker. But when I dump this process's memory, use MAT checked the number of the ThreadPoolWorker. The count just some hundreds, less than 1000, and the ctl.value of the some instance is 1610612736.
I think maybe invoke submit() method, the instanceof of ThreadPoolExecutor already finalized by jvm. I check the ThreadPoolExecutor.finalize(), when it invoked, the shutdown() method will be invoked.
Then sumbit the A$1, the ctl status arleady "SHUTDOWN", so the exception message like "rejected from java.util.concurrent.ThreadPoolExecutor@25298878[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]".
REPRODUCIBILITY :
This bug can be reproduced occasionally.
---------- BEGIN SOURCE ----------
Then I change the test case like this, and reproduce the exception
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class A implements Runnable {
public void afterProperties() {
Executors.newSingleThreadExecutor().submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
@Override
public void run() {
try {
afterProperties();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.exit(-1);
}
}
public static void main(String[] args) throws Exception {
ExecutorService execMain = Executors.newFixedThreadPool(2);
A testcase = new A();
execMain.submit(new Runnable(){
@Override
public void run() {
while(true) {
System.gc();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}});
for (;;) {
execMain.submit(testcase);
Thread.yield();
}
}
}
---------- END SOURCE ----------