-
Bug
-
Resolution: Not an Issue
-
P3
-
None
-
15.0.2
-
x86_64
-
windows
ADDITIONAL SYSTEM INFORMATION :
OS:Win10
jdk: jdk-15.0.2
jre: jdk-15.0.2
A DESCRIPTION OF THE PROBLEM :
Creates a {@code ForkJoinPool} with the given parameters. If we make parallelism equal to 0x7ffe,it's less than MAX_CAP(Obviously,0x7ffe<0x7fff). When calculating the length of the array in the constructor,the main code that (int n = (parallelism > 1) ? parallelism - 1 : 1; //At this time,n=parallelism - 1,it‘s 0x7ffd(0111 1111 1111 1101).
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1;).
The last,n+1=1000 0000 0000 0000, [(n + 1) << 1]=1 0000 0000 0000 0000,that is 17bits!!!,more than 16.We didn't realize that near the limit, doubling the capacity would take another bit。So i think the MAX_CAP shuold be 0x3fff,not to be (1<<15)-1.Only in this way can we meet the requirements of the notes“To enable this packing, we restrict maximum parallelism to (1<<15)-1 (which is far in excess of normal operating range) to allow ids, counts, and their negations (used for thresholding) to fit into 16bit subfields.”
The constructor code is as follows:
********************************************************************************************************************
static final int MAX_CAP = 0x7fff; // max #workers - 1
public ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
boolean asyncMode,
int corePoolSize,
int maximumPoolSize,
int minimumRunnable,
Predicate<? super ForkJoinPool> saturate,
long keepAliveTime,
TimeUnit unit) {
// check, encode, pack parameters
if (parallelism <= 0 || parallelism > MAX_CAP ||
maximumPoolSize < parallelism || keepAliveTime <= 0L)
throw new IllegalArgumentException();
if (factory == null)
throw new NullPointerException();
long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
long c = ((((long)(-corep) << TC_SHIFT) & TC_MASK) |
(((long)(-parallelism) << RC_SHIFT) & RC_MASK));
int m = parallelism | (asyncMode ? FIFO : 0);
int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - parallelism;
int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);
int b = ((minAvail - parallelism) & SMASK) | (maxSpares << SWIDTH);
int n = (parallelism > 1) ? parallelism - 1 : 1; // at least 2 slots
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1; // power of two, including space for submission queues
this.workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
this.workQueues = new WorkQueue[n];
this.factory = factory;
this.ueh = handler;
this.saturate = saturate;
this.keepAlive = ms;
this.bounds = b;
this.mode = m;
this.ctl = c;
checkPermission();
}
*************************************************************************************************************
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
step1:If we make parallelism equal to 0x7ffe,it's less than MAX_CAP(Obviously,0x7ffe<0x7fff).
It's mean that we give parallelism=0111 1111 1111 1110, capacity calculation:
int n = (parallelism > 1) ? parallelism - 1 : 1;
step2:
n=0111 1111 1111 1101;(n >>> 1)=0011 1111 1111 1110;
(n |= n >>> 1)=0111 1111 1111 1111
.........
(n |= n >>> 16)=0111 1111 1111 1111
step3: n+1=1000 0000 0000 0000
step4:[(n+1)<<1]= 1 0000 0000 0000 0000
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
[(n+1)<<1]= 1000 0000 0000 0000 Maximum poolIndex is 2^15-1
ACTUAL -
[(n+1)<<1]= 1 0000 0000 0000 0000 that is 17bits,exceed the last 16bits of the "ctl".
2^16-1
---------- BEGIN SOURCE ----------
Because this involves the maximum parallelism, which can be up to 32767. I have no equipment condition. But this error occurs in three lines of capacity code. The example I gave fully proves max_ Cap has errors in setting value, which is only a pure mathematical problem demonstration to find errors.I hope you can confirm this problem!
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
make the MAX_CAP = 0x7ffe,That's binary 0011 1111 1111 1111
FREQUENCY : always
OS:Win10
jdk: jdk-15.0.2
jre: jdk-15.0.2
A DESCRIPTION OF THE PROBLEM :
Creates a {@code ForkJoinPool} with the given parameters. If we make parallelism equal to 0x7ffe,it's less than MAX_CAP(Obviously,0x7ffe<0x7fff). When calculating the length of the array in the constructor,the main code that (int n = (parallelism > 1) ? parallelism - 1 : 1; //At this time,n=parallelism - 1,it‘s 0x7ffd(0111 1111 1111 1101).
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1;).
The last,n+1=1000 0000 0000 0000, [(n + 1) << 1]=1 0000 0000 0000 0000,that is 17bits!!!,more than 16.We didn't realize that near the limit, doubling the capacity would take another bit。So i think the MAX_CAP shuold be 0x3fff,not to be (1<<15)-1.Only in this way can we meet the requirements of the notes“To enable this packing, we restrict maximum parallelism to (1<<15)-1 (which is far in excess of normal operating range) to allow ids, counts, and their negations (used for thresholding) to fit into 16bit subfields.”
The constructor code is as follows:
********************************************************************************************************************
static final int MAX_CAP = 0x7fff; // max #workers - 1
public ForkJoinPool(int parallelism,
ForkJoinWorkerThreadFactory factory,
UncaughtExceptionHandler handler,
boolean asyncMode,
int corePoolSize,
int maximumPoolSize,
int minimumRunnable,
Predicate<? super ForkJoinPool> saturate,
long keepAliveTime,
TimeUnit unit) {
// check, encode, pack parameters
if (parallelism <= 0 || parallelism > MAX_CAP ||
maximumPoolSize < parallelism || keepAliveTime <= 0L)
throw new IllegalArgumentException();
if (factory == null)
throw new NullPointerException();
long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
long c = ((((long)(-corep) << TC_SHIFT) & TC_MASK) |
(((long)(-parallelism) << RC_SHIFT) & RC_MASK));
int m = parallelism | (asyncMode ? FIFO : 0);
int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - parallelism;
int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);
int b = ((minAvail - parallelism) & SMASK) | (maxSpares << SWIDTH);
int n = (parallelism > 1) ? parallelism - 1 : 1; // at least 2 slots
n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
n = (n + 1) << 1; // power of two, including space for submission queues
this.workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
this.workQueues = new WorkQueue[n];
this.factory = factory;
this.ueh = handler;
this.saturate = saturate;
this.keepAlive = ms;
this.bounds = b;
this.mode = m;
this.ctl = c;
checkPermission();
}
*************************************************************************************************************
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
step1:If we make parallelism equal to 0x7ffe,it's less than MAX_CAP(Obviously,0x7ffe<0x7fff).
It's mean that we give parallelism=0111 1111 1111 1110, capacity calculation:
int n = (parallelism > 1) ? parallelism - 1 : 1;
step2:
n=0111 1111 1111 1101;(n >>> 1)=0011 1111 1111 1110;
(n |= n >>> 1)=0111 1111 1111 1111
.........
(n |= n >>> 16)=0111 1111 1111 1111
step3: n+1=1000 0000 0000 0000
step4:[(n+1)<<1]= 1 0000 0000 0000 0000
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
[(n+1)<<1]= 1000 0000 0000 0000 Maximum poolIndex is 2^15-1
ACTUAL -
[(n+1)<<1]= 1 0000 0000 0000 0000 that is 17bits,exceed the last 16bits of the "ctl".
2^16-1
---------- BEGIN SOURCE ----------
Because this involves the maximum parallelism, which can be up to 32767. I have no equipment condition. But this error occurs in three lines of capacity code. The example I gave fully proves max_ Cap has errors in setting value, which is only a pure mathematical problem demonstration to find errors.I hope you can confirm this problem!
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
make the MAX_CAP = 0x7ffe,That's binary 0011 1111 1111 1111
FREQUENCY : always