-
Bug
-
Resolution: Fixed
-
P2
-
1.4.2
-
06
-
x86
-
windows_xp
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2101499 | 5.0 | Mark Reinhold | P2 | Resolved | Fixed | b54 |
Name: jl125535 Date: 05/12/2004
FULL PRODUCT VERSION :
J2SE v1.5beta, 1.4.2_04
ADDITIONAL OS VERSION INFORMATION :
Windows, Linux, Solaris
A DESCRIPTION OF THE PROBLEM :
I think the implemetation of java.nio.Bits#reserveMemory is not good.
Here is a part of java.nio.Bits.java source code for v1.5beta.
1. static synchronized void reserveMemory(long size) {
...
6. if (reservedMemory + size > maxMemory) {
7. System.gc();
8. try {
9. Thread.sleep(100);
10. } catch (InterruptedException x) {
11. // Restore interrupt status
12. Thread.currentThread().interrupt();
13. }
14. if (reservedMemory + size > maxMemory)
15. throw new OutOfMemoryError("Direct buffer memory");
16. }
17. reservedMemory += size;
18. }
I propose changing sleep(100) into Object.wait(100) or Object.wait() at line 9.
[Reason]
The reserveMemory method is "static synchronized".
It seems like the "sleep(100)" at line 9 is called so that that the
reservedMemory field used at line 14 can wait for the ReferenceHandler
thread to call java.nio.Bits#unreserveMemory(long).
1. static synchronized void unreserveMemory(long size) {
2. if (reservedMemory > 0) {
3. reservedMemory -= size;
4. assert (reservedMemory > -1);
5. }
6. }
However, because the sleep does not lock a Bits.class object,
and java.nio.Bits#unreserveMemory is also "static synchronied",
java.nio.Bits#unreserveMemory can not run while the
java.nio.Bits#reserveMemory is sleeping.
Here is a proposed implementaion of these methods.
- change sleep(100) into wait(100) in reserveMemory, and
- add notifyAll() as last statement in unreserveMemory
1. static synchronized void reserveMemory(long size) {
...
6. if (reservedMemory + size > maxMemory) {
7. System.gc();
8. try {
9. Bits.class.wait(100);
10. } catch (InterruptedException x) {
11. // Restore interrupt status
12. Thread.currentThread().interrupt();
13. }
14. if (reservedMemory + size > maxMemory)
15. throw new OutOfMemoryError("Direct buffer memory");
16. }
17. reservedMemory += size;
18. }
1. static synchronized void unreserveMemory(long size) {
2. if (reservedMemory > 0) {
3. reservedMemory -= size;
4. assert (reservedMemory > -1);
5. }
6. Bits.class.notifyAll();
7. }
I evaluate these implementations by using the same sample
source code as those of 4879883.
Even with -XX:MexDirectMemorySize=8k, new implementation work fine.
----
import java.nio.ByteBuffer;
public class ByteBufferTest {
public static void main(String[] args) {
for (;;) {
ByteBuffer buf = ByteBuffer.allocateDirect(8192);
}
}
}
----
I hope both of v1.4.2_05 and v1.5 release has these implementations,
or more good implemetations.
REPRODUCIBILITY :
This bug can be reproduced always.
(Incident Review ID: 265100)
======================================================================
- backported by
-
JDK-2101499 (bf) Direct memory cannot be unreserved while reserving thread sleeps
- Resolved
- relates to
-
JDK-4879883 (bf) Allocating direct buffers causes OutOfMemoryError
- Resolved